[AArch64] Accept more addressing modes for PRFM
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blobd39b8507c7570b4490ede20c523ffcf6bd533a36
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; Register numbers
22 (define_constants
23   [
24     (R0_REGNUM          0)
25     (R1_REGNUM          1)
26     (R2_REGNUM          2)
27     (R3_REGNUM          3)
28     (R4_REGNUM          4)
29     (R5_REGNUM          5)
30     (R6_REGNUM          6)
31     (R7_REGNUM          7)
32     (R8_REGNUM          8)
33     (R9_REGNUM          9)
34     (R10_REGNUM         10)
35     (R11_REGNUM         11)
36     (R12_REGNUM         12)
37     (R13_REGNUM         13)
38     (R14_REGNUM         14)
39     (R15_REGNUM         15)
40     (R16_REGNUM         16)
41     (IP0_REGNUM         16)
42     (R17_REGNUM         17)
43     (IP1_REGNUM         17)
44     (R18_REGNUM         18)
45     (R19_REGNUM         19)
46     (R20_REGNUM         20)
47     (R21_REGNUM         21)
48     (R22_REGNUM         22)
49     (R23_REGNUM         23)
50     (R24_REGNUM         24)
51     (R25_REGNUM         25)
52     (R26_REGNUM         26)
53     (R27_REGNUM         27)
54     (R28_REGNUM         28)
55     (R29_REGNUM         29)
56     (R30_REGNUM         30)
57     (LR_REGNUM          30)
58     (SP_REGNUM          31)
59     (V0_REGNUM          32)
60     (V15_REGNUM         47)
61     (V31_REGNUM         63)
62     (LAST_SAVED_REGNUM  63)
63     (SFP_REGNUM         64)
64     (AP_REGNUM          65)
65     (CC_REGNUM          66)
66   ]
69 (define_c_enum "unspec" [
70     UNSPEC_AUTI1716
71     UNSPEC_AUTISP
72     UNSPEC_CASESI
73     UNSPEC_CRC32B
74     UNSPEC_CRC32CB
75     UNSPEC_CRC32CH
76     UNSPEC_CRC32CW
77     UNSPEC_CRC32CX
78     UNSPEC_CRC32H
79     UNSPEC_CRC32W
80     UNSPEC_CRC32X
81     UNSPEC_FCVTZS
82     UNSPEC_FCVTZU
83     UNSPEC_URECPE
84     UNSPEC_FRECPE
85     UNSPEC_FRECPS
86     UNSPEC_FRECPX
87     UNSPEC_FRINTA
88     UNSPEC_FRINTI
89     UNSPEC_FRINTM
90     UNSPEC_FRINTN
91     UNSPEC_FRINTP
92     UNSPEC_FRINTX
93     UNSPEC_FRINTZ
94     UNSPEC_GOTSMALLPIC
95     UNSPEC_GOTSMALLPIC28K
96     UNSPEC_GOTSMALLTLS
97     UNSPEC_GOTTINYPIC
98     UNSPEC_GOTTINYTLS
99     UNSPEC_LD1
100     UNSPEC_LD2
101     UNSPEC_LD2_DUP
102     UNSPEC_LD3
103     UNSPEC_LD3_DUP
104     UNSPEC_LD4
105     UNSPEC_LD4_DUP
106     UNSPEC_LD2_LANE
107     UNSPEC_LD3_LANE
108     UNSPEC_LD4_LANE
109     UNSPEC_MB
110     UNSPEC_NOP
111     UNSPEC_PACI1716
112     UNSPEC_PACISP
113     UNSPEC_PRLG_STK
114     UNSPEC_RBIT
115     UNSPEC_SCVTF
116     UNSPEC_SISD_NEG
117     UNSPEC_SISD_SSHL
118     UNSPEC_SISD_USHL
119     UNSPEC_SSHL_2S
120     UNSPEC_ST1
121     UNSPEC_ST2
122     UNSPEC_ST3
123     UNSPEC_ST4
124     UNSPEC_ST2_LANE
125     UNSPEC_ST3_LANE
126     UNSPEC_ST4_LANE
127     UNSPEC_TLS
128     UNSPEC_TLSDESC
129     UNSPEC_TLSLE12
130     UNSPEC_TLSLE24
131     UNSPEC_TLSLE32
132     UNSPEC_TLSLE48
133     UNSPEC_UCVTF
134     UNSPEC_USHL_2S
135     UNSPEC_VSTRUCTDUMMY
136     UNSPEC_SP_SET
137     UNSPEC_SP_TEST
138     UNSPEC_RSQRT
139     UNSPEC_RSQRTE
140     UNSPEC_RSQRTS
141     UNSPEC_NZCV
142     UNSPEC_XPACLRI
145 (define_c_enum "unspecv" [
146     UNSPECV_EH_RETURN           ; Represent EH_RETURN
147     UNSPECV_GET_FPCR            ; Represent fetch of FPCR content.
148     UNSPECV_SET_FPCR            ; Represent assign of FPCR content.
149     UNSPECV_GET_FPSR            ; Represent fetch of FPSR content.
150     UNSPECV_SET_FPSR            ; Represent assign of FPSR content.
151     UNSPECV_BLOCKAGE            ; Represent a blockage
152     UNSPECV_PROBE_STACK_RANGE   ; Represent stack range probing.
153   ]
156 ;; If further include files are added the defintion of MD_INCLUDES
157 ;; must be updated.
159 (include "constraints.md")
160 (include "predicates.md")
161 (include "iterators.md")
163 ;; -------------------------------------------------------------------
164 ;; Instruction types and attributes
165 ;; -------------------------------------------------------------------
167 ; The "type" attribute is included here from AArch32 backend to be able
168 ; to share pipeline descriptions.
169 (include "../arm/types.md")
171 ;; It is important to set the fp or simd attributes to yes when a pattern
172 ;; alternative uses the FP or SIMD register files, usually signified by use of
173 ;; the 'w' constraint.  This will ensure that the alternative will be
174 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
175 ;; architecture extensions.  If all the alternatives in a pattern use the
176 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
177 ;; or TARGET_SIMD.
179 ;; Attribute that specifies whether or not the instruction touches fp
180 ;; registers.  When this is set to yes for an alternative, that alternative
181 ;; will be disabled when !TARGET_FLOAT.
182 (define_attr "fp" "no,yes" (const_string "no"))
184 ;; Attribute that specifies whether or not the instruction touches simd
185 ;; registers.  When this is set to yes for an alternative, that alternative
186 ;; will be disabled when !TARGET_SIMD.
187 (define_attr "simd" "no,yes" (const_string "no"))
189 (define_attr "length" ""
190   (const_int 4))
192 ;; Attribute that controls whether an alternative is enabled or not.
193 ;; Currently it is only used to disable alternatives which touch fp or simd
194 ;; registers when -mgeneral-regs-only is specified.
195 (define_attr "enabled" "no,yes"
196   (cond [(ior
197         (and (eq_attr "fp" "yes")
198              (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
199         (and (eq_attr "simd" "yes")
200              (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
201              (const_string "no")
202         ] (const_string "yes")))
204 ;; Attribute that specifies whether we are dealing with a branch to a
205 ;; label that is far away, i.e. further away than the maximum/minimum
206 ;; representable in a signed 21-bits number.
207 ;; 0 :=: no
208 ;; 1 :=: yes
209 (define_attr "far_branch" "" (const_int 0))
211 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
212 ;; no predicated insns.
213 (define_attr "predicated" "yes,no" (const_string "no"))
215 ;; -------------------------------------------------------------------
216 ;; Pipeline descriptions and scheduling
217 ;; -------------------------------------------------------------------
219 ;; Processor types.
220 (include "aarch64-tune.md")
222 ;; Scheduling
223 (include "../arm/cortex-a53.md")
224 (include "../arm/cortex-a57.md")
225 (include "../arm/exynos-m1.md")
226 (include "thunderx.md")
227 (include "../arm/xgene1.md")
228 (include "thunderx2t99.md")
230 ;; -------------------------------------------------------------------
231 ;; Jumps and other miscellaneous insns
232 ;; -------------------------------------------------------------------
234 (define_insn "indirect_jump"
235   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
236   ""
237   "br\\t%0"
238   [(set_attr "type" "branch")]
241 (define_insn "jump"
242   [(set (pc) (label_ref (match_operand 0 "" "")))]
243   ""
244   "b\\t%l0"
245   [(set_attr "type" "branch")]
248 (define_expand "cbranch<mode>4"
249   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
250                             [(match_operand:GPI 1 "register_operand" "")
251                              (match_operand:GPI 2 "aarch64_plus_operand" "")])
252                            (label_ref (match_operand 3 "" ""))
253                            (pc)))]
254   ""
255   "
256   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
257                                          operands[2]);
258   operands[2] = const0_rtx;
259   "
262 (define_expand "cbranch<mode>4"
263   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
264                             [(match_operand:GPF 1 "register_operand" "")
265                              (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
266                            (label_ref (match_operand 3 "" ""))
267                            (pc)))]
268   ""
269   "
270   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
271                                          operands[2]);
272   operands[2] = const0_rtx;
273   "
276 (define_expand "cbranchcc4"
277   [(set (pc) (if_then_else
278               (match_operator 0 "aarch64_comparison_operator"
279                [(match_operand 1 "cc_register" "")
280                 (match_operand 2 "const0_operand")])
281               (label_ref (match_operand 3 "" ""))
282               (pc)))]
283   ""
284   "")
286 (define_insn "ccmp<mode>"
287   [(set (match_operand:CC 1 "cc_register" "")
288         (if_then_else:CC
289           (match_operator 4 "aarch64_comparison_operator"
290            [(match_operand 0 "cc_register" "")
291             (const_int 0)])
292           (compare:CC
293             (match_operand:GPI 2 "register_operand" "r,r,r")
294             (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
295           (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
296   ""
297   "@
298    ccmp\\t%<w>2, %<w>3, %k5, %m4
299    ccmp\\t%<w>2, %3, %k5, %m4
300    ccmn\\t%<w>2, #%n3, %k5, %m4"
301   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
304 (define_insn "fccmp<mode>"
305   [(set (match_operand:CCFP 1 "cc_register" "")
306         (if_then_else:CCFP
307           (match_operator 4 "aarch64_comparison_operator"
308            [(match_operand 0 "cc_register" "")
309             (const_int 0)])
310           (compare:CCFP
311             (match_operand:GPF 2 "register_operand" "w")
312             (match_operand:GPF 3 "register_operand" "w"))
313           (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
314   "TARGET_FLOAT"
315   "fccmp\\t%<s>2, %<s>3, %k5, %m4"
316   [(set_attr "type" "fccmp<s>")]
319 (define_insn "fccmpe<mode>"
320   [(set (match_operand:CCFPE 1 "cc_register" "")
321          (if_then_else:CCFPE
322           (match_operator 4 "aarch64_comparison_operator"
323            [(match_operand 0 "cc_register" "")
324           (const_int 0)])
325            (compare:CCFPE
326             (match_operand:GPF 2 "register_operand" "w")
327             (match_operand:GPF 3 "register_operand" "w"))
328           (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
329   "TARGET_FLOAT"
330   "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
331   [(set_attr "type" "fccmp<s>")]
334 ;; Expansion of signed mod by a power of 2 using CSNEG.
335 ;; For x0 % n where n is a power of 2 produce:
336 ;; negs   x1, x0
337 ;; and    x0, x0, #(n - 1)
338 ;; and    x1, x1, #(n - 1)
339 ;; csneg  x0, x0, x1, mi
341 (define_expand "mod<mode>3"
342   [(match_operand:GPI 0 "register_operand" "")
343    (match_operand:GPI 1 "register_operand" "")
344    (match_operand:GPI 2 "const_int_operand" "")]
345   ""
346   {
347     HOST_WIDE_INT val = INTVAL (operands[2]);
349     if (val <= 0
350        || exact_log2 (val) <= 0
351        || !aarch64_bitmask_imm (val - 1, <MODE>mode))
352       FAIL;
354     rtx mask = GEN_INT (val - 1);
356     /* In the special case of x0 % 2 we can do the even shorter:
357         cmp    x0, xzr
358         and    x0, x0, 1
359         cneg   x0, x0, lt.  */
360     if (val == 2)
361       {
362         rtx masked = gen_reg_rtx (<MODE>mode);
363         rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
364         emit_insn (gen_and<mode>3 (masked, operands[1], mask));
365         rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
366         emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
367         DONE;
368       }
370     rtx neg_op = gen_reg_rtx (<MODE>mode);
371     rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
373     /* Extract the condition register and mode.  */
374     rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
375     rtx cc_reg = SET_DEST (cmp);
376     rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
378     rtx masked_pos = gen_reg_rtx (<MODE>mode);
379     emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
381     rtx masked_neg = gen_reg_rtx (<MODE>mode);
382     emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
384     emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
385                                        masked_neg, masked_pos));
386     DONE;
387   }
390 (define_insn "condjump"
391   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
392                             [(match_operand 1 "cc_register" "") (const_int 0)])
393                            (label_ref (match_operand 2 "" ""))
394                            (pc)))]
395   ""
396   {
397     if (get_attr_length (insn) == 8)
398       return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
399     else
400       return  "b%m0\\t%l2";
401   }
402   [(set_attr "type" "branch")
403    (set (attr "length")
404         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
405                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
406                       (const_int 4)
407                       (const_int 8)))
408    (set (attr "far_branch")
409         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
410                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
411                       (const_int 0)
412                       (const_int 1)))]
415 ;; For a 24-bit immediate CST we can optimize the compare for equality
416 ;; and branch sequence from:
417 ;;      mov     x0, #imm1
418 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
419 ;;      cmp     x1, x0
420 ;;      b<ne,eq> .Label
421 ;; into the shorter:
422 ;;      sub     x0, x1, #(CST & 0xfff000)
423 ;;      subs    x0, x0, #(CST & 0x000fff)
424 ;;      b<ne,eq> .Label
425 (define_insn_and_split "*compare_condjump<mode>"
426   [(set (pc) (if_then_else (EQL
427                               (match_operand:GPI 0 "register_operand" "r")
428                               (match_operand:GPI 1 "aarch64_imm24" "n"))
429                            (label_ref:P (match_operand 2 "" ""))
430                            (pc)))]
431   "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
432    && !aarch64_plus_operand (operands[1], <MODE>mode)
433    && !reload_completed"
434   "#"
435   "&& true"
436   [(const_int 0)]
437   {
438     HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
439     HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
440     rtx tmp = gen_reg_rtx (<MODE>mode);
441     emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
442     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
443     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
444     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
445     emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
446     DONE;
447   }
450 (define_expand "casesi"
451   [(match_operand:SI 0 "register_operand" "")   ; Index
452    (match_operand:SI 1 "const_int_operand" "")  ; Lower bound
453    (match_operand:SI 2 "const_int_operand" "")  ; Total range
454    (match_operand:DI 3 "" "")                   ; Table label
455    (match_operand:DI 4 "" "")]                  ; Out of range label
456   ""
457   {
458     if (operands[1] != const0_rtx)
459       {
460         rtx reg = gen_reg_rtx (SImode);
462         /* Canonical RTL says that if you have:
464            (minus (X) (CONST))
466            then this should be emitted as:
468            (plus (X) (-CONST))
470            The use of trunc_int_for_mode ensures that the resulting
471            constant can be represented in SImode, this is important
472            for the corner case where operand[1] is INT_MIN.  */
474         operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
476         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
477               (operands[1], SImode))
478           operands[1] = force_reg (SImode, operands[1]);
479         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
480         operands[0] = reg;
481       }
483     if (!aarch64_plus_operand (operands[2], SImode))
484       operands[2] = force_reg (SImode, operands[2]);
485     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
486                                                  const0_rtx),
487                                     operands[0], operands[2], operands[4]));
489     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
490     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
491                                          operands[3]));
492     DONE;
493   }
496 (define_insn "casesi_dispatch"
497   [(parallel
498     [(set (pc)
499           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
500                            (match_operand:SI 1 "register_operand" "r")]
501                         UNSPEC_CASESI)))
502      (clobber (reg:CC CC_REGNUM))
503      (clobber (match_scratch:DI 3 "=r"))
504      (clobber (match_scratch:DI 4 "=r"))
505      (use (label_ref (match_operand 2 "" "")))])]
506   ""
507   "*
508   return aarch64_output_casesi (operands);
509   "
510   [(set_attr "length" "16")
511    (set_attr "type" "branch")]
514 (define_insn "nop"
515   [(unspec[(const_int 0)] UNSPEC_NOP)]
516   ""
517   "nop"
518   [(set_attr "type" "no_insn")]
521 (define_insn "prefetch"
522   [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
523             (match_operand:QI 1 "const_int_operand" "")
524             (match_operand:QI 2 "const_int_operand" ""))]
525   ""
526   {
527     const char * pftype[2][4] =
528     {
529       {"prfm\\tPLDL1STRM, %0",
530        "prfm\\tPLDL3KEEP, %0",
531        "prfm\\tPLDL2KEEP, %0",
532        "prfm\\tPLDL1KEEP, %0"},
533       {"prfm\\tPSTL1STRM, %0",
534        "prfm\\tPSTL3KEEP, %0",
535        "prfm\\tPSTL2KEEP, %0",
536        "prfm\\tPSTL1KEEP, %0"},
537     };
539     int locality = INTVAL (operands[2]);
541     gcc_assert (IN_RANGE (locality, 0, 3));
543     /* PRFM accepts the same addresses as a 64-bit LDR so wrap
544        the address into a DImode MEM so that aarch64_print_operand knows
545        how to print it.  */
546     operands[0] = gen_rtx_MEM (DImode, operands[0]);
547     return pftype[INTVAL(operands[1])][locality];
548   }
549   [(set_attr "type" "load1")]
552 (define_insn "trap"
553   [(trap_if (const_int 1) (const_int 8))]
554   ""
555   "brk #1000"
556   [(set_attr "type" "trap")])
558 (define_expand "prologue"
559   [(clobber (const_int 0))]
560   ""
561   "
562   aarch64_expand_prologue ();
563   DONE;
564   "
567 (define_expand "epilogue"
568   [(clobber (const_int 0))]
569   ""
570   "
571   aarch64_expand_epilogue (false);
572   DONE;
573   "
576 (define_expand "sibcall_epilogue"
577   [(clobber (const_int 0))]
578   ""
579   "
580   aarch64_expand_epilogue (true);
581   DONE;
582   "
585 (define_insn "*do_return"
586   [(return)]
587   ""
588   {
589     if (aarch64_return_address_signing_enabled ()
590         && TARGET_ARMV8_3
591         && !crtl->calls_eh_return)
592       return "retaa";
594     return "ret";
595   }
596   [(set_attr "type" "branch")]
599 (define_expand "return"
600   [(simple_return)]
601   "aarch64_use_return_insn_p ()"
602   ""
605 (define_insn "simple_return"
606   [(simple_return)]
607   ""
608   "ret"
609   [(set_attr "type" "branch")]
612 (define_insn "*cb<optab><mode>1"
613   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
614                                 (const_int 0))
615                            (label_ref (match_operand 1 "" ""))
616                            (pc)))]
617   ""
618   {
619     if (get_attr_length (insn) == 8)
620       return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
621     else
622       return "<cbz>\\t%<w>0, %l1";
623   }
624   [(set_attr "type" "branch")
625    (set (attr "length")
626         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
627                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
628                       (const_int 4)
629                       (const_int 8)))
630    (set (attr "far_branch")
631         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
632                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
633                       (const_int 0)
634                       (const_int 1)))]
637 (define_insn "*tb<optab><mode>1"
638   [(set (pc) (if_then_else
639               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
640                                     (const_int 1)
641                                     (match_operand 1
642                                       "aarch64_simd_shift_imm_<mode>" "n"))
643                    (const_int 0))
644              (label_ref (match_operand 2 "" ""))
645              (pc)))
646    (clobber (reg:CC CC_REGNUM))]
647   ""
648   {
649     if (get_attr_length (insn) == 8)
650       {
651         if (get_attr_far_branch (insn) == 1)
652           return aarch64_gen_far_branch (operands, 2, "Ltb",
653                                          "<inv_tb>\\t%<w>0, %1, ");
654         else
655           {
656             operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
657             return "tst\t%<w>0, %1\;<bcond>\t%l2";
658           }
659       }
660     else
661       return "<tbz>\t%<w>0, %1, %l2";
662   }
663   [(set_attr "type" "branch")
664    (set (attr "length")
665         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
666                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
667                       (const_int 4)
668                       (const_int 8)))
669    (set (attr "far_branch")
670         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
671                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
672                       (const_int 0)
673                       (const_int 1)))]
677 (define_insn "*cb<optab><mode>1"
678   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
679                                  (const_int 0))
680                            (label_ref (match_operand 1 "" ""))
681                            (pc)))
682    (clobber (reg:CC CC_REGNUM))]
683   ""
684   {
685     if (get_attr_length (insn) == 8)
686       {
687         if (get_attr_far_branch (insn) == 1)
688           return aarch64_gen_far_branch (operands, 1, "Ltb",
689                                          "<inv_tb>\\t%<w>0, <sizem1>, ");
690         else
691           {
692             char buf[64];
693             uint64_t val = ((uint64_t) 1)
694                 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
695             sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
696             output_asm_insn (buf, operands);
697             return "<bcond>\t%l1";
698           }
699       }
700     else
701       return "<tbz>\t%<w>0, <sizem1>, %l1";
702   }
703   [(set_attr "type" "branch")
704    (set (attr "length")
705         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
706                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
707                       (const_int 4)
708                       (const_int 8)))
709    (set (attr "far_branch")
710         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
711                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
712                       (const_int 0)
713                       (const_int 1)))]
716 ;; -------------------------------------------------------------------
717 ;; Subroutine calls and sibcalls
718 ;; -------------------------------------------------------------------
720 (define_expand "call_internal"
721   [(parallel [(call (match_operand 0 "memory_operand" "")
722                     (match_operand 1 "general_operand" ""))
723               (use (match_operand 2 "" ""))
724               (clobber (reg:DI LR_REGNUM))])])
726 (define_expand "call"
727   [(parallel [(call (match_operand 0 "memory_operand" "")
728                     (match_operand 1 "general_operand" ""))
729               (use (match_operand 2 "" ""))
730               (clobber (reg:DI LR_REGNUM))])]
731   ""
732   "
733   {
734     rtx callee, pat;
736     /* In an untyped call, we can get NULL for operand 2.  */
737     if (operands[2] == NULL)
738       operands[2] = const0_rtx;
740     /* Decide if we should generate indirect calls by loading the
741        64-bit address of the callee into a register before performing
742        the branch-and-link.  */
743     callee = XEXP (operands[0], 0);
744     if (GET_CODE (callee) == SYMBOL_REF
745         ? (aarch64_is_long_call_p (callee)
746            || aarch64_is_noplt_call_p (callee))
747         : !REG_P (callee))
748       XEXP (operands[0], 0) = force_reg (Pmode, callee);
750     pat = gen_call_internal (operands[0], operands[1], operands[2]);
751     aarch64_emit_call_insn (pat);
752     DONE;
753   }"
756 (define_insn "*call_reg"
757   [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
758          (match_operand 1 "" ""))
759    (use (match_operand 2 "" ""))
760    (clobber (reg:DI LR_REGNUM))]
761   ""
762   "blr\\t%0"
763   [(set_attr "type" "call")]
766 (define_insn "*call_symbol"
767   [(call (mem:DI (match_operand:DI 0 "" ""))
768          (match_operand 1 "" ""))
769    (use (match_operand 2 "" ""))
770    (clobber (reg:DI LR_REGNUM))]
771   "GET_CODE (operands[0]) == SYMBOL_REF
772    && !aarch64_is_long_call_p (operands[0])
773    && !aarch64_is_noplt_call_p (operands[0])"
774   "bl\\t%a0"
775   [(set_attr "type" "call")]
778 (define_expand "call_value_internal"
779   [(parallel [(set (match_operand 0 "" "")
780                    (call (match_operand 1 "memory_operand" "")
781                          (match_operand 2 "general_operand" "")))
782               (use (match_operand 3 "" ""))
783               (clobber (reg:DI LR_REGNUM))])])
785 (define_expand "call_value"
786   [(parallel [(set (match_operand 0 "" "")
787                    (call (match_operand 1 "memory_operand" "")
788                          (match_operand 2 "general_operand" "")))
789               (use (match_operand 3 "" ""))
790               (clobber (reg:DI LR_REGNUM))])]
791   ""
792   "
793   {
794     rtx callee, pat;
796     /* In an untyped call, we can get NULL for operand 3.  */
797     if (operands[3] == NULL)
798       operands[3] = const0_rtx;
800     /* Decide if we should generate indirect calls by loading the
801        64-bit address of the callee into a register before performing
802        the branch-and-link.  */
803     callee = XEXP (operands[1], 0);
804     if (GET_CODE (callee) == SYMBOL_REF
805         ? (aarch64_is_long_call_p (callee)
806            || aarch64_is_noplt_call_p (callee))
807         : !REG_P (callee))
808       XEXP (operands[1], 0) = force_reg (Pmode, callee);
810     pat = gen_call_value_internal (operands[0], operands[1], operands[2],
811                                    operands[3]);
812     aarch64_emit_call_insn (pat);
813     DONE;
814   }"
817 (define_insn "*call_value_reg"
818   [(set (match_operand 0 "" "")
819         (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
820                       (match_operand 2 "" "")))
821    (use (match_operand 3 "" ""))
822    (clobber (reg:DI LR_REGNUM))]
823   ""
824   "blr\\t%1"
825   [(set_attr "type" "call")]
829 (define_insn "*call_value_symbol"
830   [(set (match_operand 0 "" "")
831         (call (mem:DI (match_operand:DI 1 "" ""))
832               (match_operand 2 "" "")))
833    (use (match_operand 3 "" ""))
834    (clobber (reg:DI LR_REGNUM))]
835   "GET_CODE (operands[1]) == SYMBOL_REF
836    && !aarch64_is_long_call_p (operands[1])
837    && !aarch64_is_noplt_call_p (operands[1])"
838   "bl\\t%a1"
839   [(set_attr "type" "call")]
842 (define_expand "sibcall_internal"
843   [(parallel [(call (match_operand 0 "memory_operand" "")
844                     (match_operand 1 "general_operand" ""))
845               (return)
846               (use (match_operand 2 "" ""))])])
848 (define_expand "sibcall"
849   [(parallel [(call (match_operand 0 "memory_operand" "")
850                     (match_operand 1 "general_operand" ""))
851               (return)
852               (use (match_operand 2 "" ""))])]
853   ""
854   {
855     rtx pat;
856     rtx callee = XEXP (operands[0], 0);
857     if (!REG_P (callee)
858        && ((GET_CODE (callee) != SYMBOL_REF)
859            || aarch64_is_noplt_call_p (callee)))
860       XEXP (operands[0], 0) = force_reg (Pmode, callee);
862     if (operands[2] == NULL_RTX)
863       operands[2] = const0_rtx;
865     pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
866     aarch64_emit_call_insn (pat);
867     DONE;
868   }
871 (define_expand "sibcall_value_internal"
872   [(parallel [(set (match_operand 0 "" "")
873                    (call (match_operand 1 "memory_operand" "")
874                          (match_operand 2 "general_operand" "")))
875               (return)
876               (use (match_operand 3 "" ""))])])
878 (define_expand "sibcall_value"
879   [(parallel [(set (match_operand 0 "" "")
880                    (call (match_operand 1 "memory_operand" "")
881                          (match_operand 2 "general_operand" "")))
882               (return)
883               (use (match_operand 3 "" ""))])]
884   ""
885   {
886     rtx pat;
887     rtx callee = XEXP (operands[1], 0);
888     if (!REG_P (callee)
889        && ((GET_CODE (callee) != SYMBOL_REF)
890            || aarch64_is_noplt_call_p (callee)))
891       XEXP (operands[1], 0) = force_reg (Pmode, callee);
893     if (operands[3] == NULL_RTX)
894       operands[3] = const0_rtx;
896     pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
897                                       operands[3]);
898     aarch64_emit_call_insn (pat);
899     DONE;
900   }
903 (define_insn "*sibcall_insn"
904   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
905          (match_operand 1 "" ""))
906    (return)
907    (use (match_operand 2 "" ""))]
908   "SIBLING_CALL_P (insn)"
909   "@
910    br\\t%0
911    b\\t%a0"
912   [(set_attr "type" "branch, branch")]
915 (define_insn "*sibcall_value_insn"
916   [(set (match_operand 0 "" "")
917         (call (mem:DI
918                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
919               (match_operand 2 "" "")))
920    (return)
921    (use (match_operand 3 "" ""))]
922   "SIBLING_CALL_P (insn)"
923   "@
924    br\\t%1
925    b\\t%a1"
926   [(set_attr "type" "branch, branch")]
929 ;; Call subroutine returning any type.
931 (define_expand "untyped_call"
932   [(parallel [(call (match_operand 0 "")
933                     (const_int 0))
934               (match_operand 1 "")
935               (match_operand 2 "")])]
936   ""
938   int i;
940   emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
942   for (i = 0; i < XVECLEN (operands[2], 0); i++)
943     {
944       rtx set = XVECEXP (operands[2], 0, i);
945       emit_move_insn (SET_DEST (set), SET_SRC (set));
946     }
948   /* The optimizer does not know that the call sets the function value
949      registers we stored in the result block.  We avoid problems by
950      claiming that all hard registers are used and clobbered at this
951      point.  */
952   emit_insn (gen_blockage ());
953   DONE;
956 ;; -------------------------------------------------------------------
957 ;; Moves
958 ;; -------------------------------------------------------------------
960 (define_expand "mov<mode>"
961   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
962         (match_operand:SHORT 1 "general_operand" ""))]
963   ""
964   "
965     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
966       operands[1] = force_reg (<MODE>mode, operands[1]);
967   "
970 (define_insn "*mov<mode>_aarch64"
971   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,   *w,r,*w, m, m, r,*w,*w")
972         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
973   "(register_operand (operands[0], <MODE>mode)
974     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
976    switch (which_alternative)
977      {
978      case 0:
979        return "mov\t%w0, %w1";
980      case 1:
981        return "mov\t%w0, %1";
982      case 2:
983        return aarch64_output_scalar_simd_mov_immediate (operands[1],
984                                                         <MODE>mode);
985      case 3:
986        return "ldr<size>\t%w0, %1";
987      case 4:
988        return "ldr\t%<size>0, %1";
989      case 5:
990        return "str<size>\t%w1, %0";
991      case 6:
992        return "str\t%<size>1, %0";
993      case 7:
994        return "umov\t%w0, %1.<v>[0]";
995      case 8:
996        return "dup\t%0.<Vallxd>, %w1";
997      case 9:
998        return "dup\t%<Vetype>0, %1.<v>[0]";
999      default:
1000        gcc_unreachable ();
1001      }
1003   [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
1004                      neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1005    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
1008 (define_expand "mov<mode>"
1009   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
1010         (match_operand:GPI 1 "general_operand" ""))]
1011   ""
1012   "
1013     if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
1014         && <MODE>mode == DImode
1015         && aarch64_split_dimode_const_store (operands[0], operands[1]))
1016       DONE;
1018     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1019       operands[1] = force_reg (<MODE>mode, operands[1]);
1021     /* FIXME: RR we still need to fix up what we are doing with
1022        symbol_refs and other types of constants.  */
1023     if (CONSTANT_P (operands[1])
1024         && !CONST_INT_P (operands[1]))
1025      {
1026        aarch64_expand_mov_immediate (operands[0], operands[1]);
1027        DONE;
1028      }
1029   "
1032 (define_insn_and_split "*movsi_aarch64"
1033   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r  ,*w, r,*w")
1034         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1035   "(register_operand (operands[0], SImode)
1036     || aarch64_reg_or_zero (operands[1], SImode))"
1037   "@
1038    mov\\t%w0, %w1
1039    mov\\t%w0, %w1
1040    mov\\t%w0, %w1
1041    mov\\t%w0, %1
1042    #
1043    ldr\\t%w0, %1
1044    ldr\\t%s0, %1
1045    str\\t%w1, %0
1046    str\\t%s1, %0
1047    adr\\t%x0, %a1
1048    adrp\\t%x0, %A1
1049    fmov\\t%s0, %w1
1050    fmov\\t%w0, %s1
1051    fmov\\t%s0, %s1"
1052    "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1053     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1054    [(const_int 0)]
1055    "{
1056        aarch64_expand_mov_immediate (operands[0], operands[1]);
1057        DONE;
1058     }"
1059   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1060                      adr,adr,f_mcr,f_mrc,fmov")
1061    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1064 (define_insn_and_split "*movdi_aarch64"
1065   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r,  *w, r,*w,w")
1066         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1067   "(register_operand (operands[0], DImode)
1068     || aarch64_reg_or_zero (operands[1], DImode))"
1069   "@
1070    mov\\t%x0, %x1
1071    mov\\t%0, %x1
1072    mov\\t%x0, %1
1073    mov\\t%x0, %1
1074    #
1075    ldr\\t%x0, %1
1076    ldr\\t%d0, %1
1077    str\\t%x1, %0
1078    str\\t%d1, %0
1079    adr\\t%x0, %a1
1080    adrp\\t%x0, %A1
1081    fmov\\t%d0, %x1
1082    fmov\\t%x0, %d1
1083    fmov\\t%d0, %d1
1084    movi\\t%d0, %1"
1085    "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1086     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1087    [(const_int 0)]
1088    "{
1089        aarch64_expand_mov_immediate (operands[0], operands[1]);
1090        DONE;
1091     }"
1092   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1093                      adr,adr,f_mcr,f_mrc,fmov,neon_move")
1094    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1095    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1098 (define_insn "insv_imm<mode>"
1099   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1100                           (const_int 16)
1101                           (match_operand:GPI 1 "const_int_operand" "n"))
1102         (match_operand:GPI 2 "const_int_operand" "n"))]
1103   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1104    && UINTVAL (operands[1]) % 16 == 0"
1105   "movk\\t%<w>0, %X2, lsl %1"
1106   [(set_attr "type" "mov_imm")]
1109 (define_expand "movti"
1110   [(set (match_operand:TI 0 "nonimmediate_operand" "")
1111         (match_operand:TI 1 "general_operand" ""))]
1112   ""
1113   "
1114     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1115       operands[1] = force_reg (TImode, operands[1]);
1116   "
1119 (define_insn "*movti_aarch64"
1120   [(set (match_operand:TI 0
1121          "nonimmediate_operand"  "=r, *w,r ,*w,r,m,m,*w,m")
1122         (match_operand:TI 1
1123          "aarch64_movti_operand" " rn,r ,*w,*w,m,r,Z, m,*w"))]
1124   "(register_operand (operands[0], TImode)
1125     || aarch64_reg_or_zero (operands[1], TImode))"
1126   "@
1127    #
1128    #
1129    #
1130    orr\\t%0.16b, %1.16b, %1.16b
1131    ldp\\t%0, %H0, %1
1132    stp\\t%1, %H1, %0
1133    stp\\txzr, xzr, %0
1134    ldr\\t%q0, %1
1135    str\\t%q1, %0"
1136   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1137                              load2,store2,store2,f_loadd,f_stored")
1138    (set_attr "length" "8,8,8,4,4,4,4,4,4")
1139    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1140    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1143 ;; Split a TImode register-register or register-immediate move into
1144 ;; its component DImode pieces, taking care to handle overlapping
1145 ;; source and dest registers.
1146 (define_split
1147    [(set (match_operand:TI 0 "register_operand" "")
1148          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1149   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1150   [(const_int 0)]
1152   aarch64_split_128bit_move (operands[0], operands[1]);
1153   DONE;
1156 (define_expand "mov<mode>"
1157   [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1158         (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1159   ""
1160   {
1161     if (!TARGET_FLOAT)
1162       {
1163         aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1164         FAIL;
1165       }
1167     if (GET_CODE (operands[0]) == MEM
1168         && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1169               && aarch64_float_const_zero_rtx_p (operands[1])))
1170       operands[1] = force_reg (<MODE>mode, operands[1]);
1171   }
1174 (define_insn "*movhf_aarch64"
1175   [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w  ,?r,w,w,m,r,m ,r")
1176         (match_operand:HF 1 "general_operand"      "Y ,?rY, w,w,m,w,m,rY,r"))]
1177   "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1178     || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1179   "@
1180    movi\\t%0.4h, #0
1181    mov\\t%0.h[0], %w1
1182    umov\\t%w0, %1.h[0]
1183    mov\\t%0.h[0], %1.h[0]
1184    ldr\\t%h0, %1
1185    str\\t%h1, %0
1186    ldrh\\t%w0, %1
1187    strh\\t%w1, %0
1188    mov\\t%w0, %w1"
1189   [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1190                      f_loads,f_stores,load1,store1,mov_reg")
1191    (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1194 (define_insn "*movsf_aarch64"
1195   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1196         (match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1197   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1198     || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1199   "@
1200    movi\\t%0.2s, #0
1201    fmov\\t%s0, %w1
1202    fmov\\t%w0, %s1
1203    fmov\\t%s0, %s1
1204    fmov\\t%s0, %1
1205    ldr\\t%s0, %1
1206    str\\t%s1, %0
1207    ldr\\t%w0, %1
1208    str\\t%w1, %0
1209    mov\\t%w0, %w1"
1210   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1211                      f_loads,f_stores,load1,store1,mov_reg")
1212    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1215 (define_insn "*movdf_aarch64"
1216   [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1217         (match_operand:DF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1218   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1219     || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1220   "@
1221    movi\\t%d0, #0
1222    fmov\\t%d0, %x1
1223    fmov\\t%x0, %d1
1224    fmov\\t%d0, %d1
1225    fmov\\t%d0, %1
1226    ldr\\t%d0, %1
1227    str\\t%d1, %0
1228    ldr\\t%x0, %1
1229    str\\t%x1, %0
1230    mov\\t%x0, %x1"
1231   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1232                      f_loadd,f_stored,load1,store1,mov_reg")
1233    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1236 (define_insn "*movtf_aarch64"
1237   [(set (match_operand:TF 0
1238          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1239         (match_operand:TF 1
1240          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1241   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1242     || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1243   "@
1244    orr\\t%0.16b, %1.16b, %1.16b
1245    #
1246    #
1247    #
1248    movi\\t%0.2d, #0
1249    fmov\\t%s0, wzr
1250    ldr\\t%q0, %1
1251    str\\t%q1, %0
1252    ldp\\t%0, %H0, %1
1253    stp\\t%1, %H1, %0
1254    stp\\txzr, xzr, %0"
1255   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1256                      f_loadd,f_stored,load2,store2,store2")
1257    (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1258    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1261 (define_split
1262    [(set (match_operand:TF 0 "register_operand" "")
1263          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1264   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1265   [(const_int 0)]
1266   {
1267     aarch64_split_128bit_move (operands[0], operands[1]);
1268     DONE;
1269   }
1272 ;; 0 is dst
1273 ;; 1 is src
1274 ;; 2 is size of move in bytes
1275 ;; 3 is alignment
1277 (define_expand "movmemdi"
1278   [(match_operand:BLK 0 "memory_operand")
1279    (match_operand:BLK 1 "memory_operand")
1280    (match_operand:DI 2 "immediate_operand")
1281    (match_operand:DI 3 "immediate_operand")]
1282    "!STRICT_ALIGNMENT"
1284   if (aarch64_expand_movmem (operands))
1285     DONE;
1286   FAIL;
1290 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1291 ;; fairly lax checking on the second memory operation.
1292 (define_insn "load_pairsi"
1293   [(set (match_operand:SI 0 "register_operand" "=r,*w")
1294         (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1295    (set (match_operand:SI 2 "register_operand" "=r,*w")
1296         (match_operand:SI 3 "memory_operand" "m,m"))]
1297   "rtx_equal_p (XEXP (operands[3], 0),
1298                 plus_constant (Pmode,
1299                                XEXP (operands[1], 0),
1300                                GET_MODE_SIZE (SImode)))"
1301   "@
1302    ldp\\t%w0, %w2, %1
1303    ldp\\t%s0, %s2, %1"
1304   [(set_attr "type" "load2,neon_load1_2reg")
1305    (set_attr "fp" "*,yes")]
1308 (define_insn "load_pairdi"
1309   [(set (match_operand:DI 0 "register_operand" "=r,*w")
1310         (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1311    (set (match_operand:DI 2 "register_operand" "=r,*w")
1312         (match_operand:DI 3 "memory_operand" "m,m"))]
1313   "rtx_equal_p (XEXP (operands[3], 0),
1314                 plus_constant (Pmode,
1315                                XEXP (operands[1], 0),
1316                                GET_MODE_SIZE (DImode)))"
1317   "@
1318    ldp\\t%x0, %x2, %1
1319    ldp\\t%d0, %d2, %1"
1320   [(set_attr "type" "load2,neon_load1_2reg")
1321    (set_attr "fp" "*,yes")]
1325 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1326 ;; fairly lax checking on the second memory operation.
1327 (define_insn "store_pairsi"
1328   [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1329         (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1330    (set (match_operand:SI 2 "memory_operand" "=m,m")
1331         (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1332   "rtx_equal_p (XEXP (operands[2], 0),
1333                 plus_constant (Pmode,
1334                                XEXP (operands[0], 0),
1335                                GET_MODE_SIZE (SImode)))"
1336   "@
1337    stp\\t%w1, %w3, %0
1338    stp\\t%s1, %s3, %0"
1339   [(set_attr "type" "store2,neon_store1_2reg")
1340    (set_attr "fp" "*,yes")]
1343 (define_insn "store_pairdi"
1344   [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1345         (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1346    (set (match_operand:DI 2 "memory_operand" "=m,m")
1347         (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1348   "rtx_equal_p (XEXP (operands[2], 0),
1349                 plus_constant (Pmode,
1350                                XEXP (operands[0], 0),
1351                                GET_MODE_SIZE (DImode)))"
1352   "@
1353    stp\\t%x1, %x3, %0
1354    stp\\t%d1, %d3, %0"
1355   [(set_attr "type" "store2,neon_store1_2reg")
1356    (set_attr "fp" "*,yes")]
1359 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1360 ;; fairly lax checking on the second memory operation.
1361 (define_insn "load_pairsf"
1362   [(set (match_operand:SF 0 "register_operand" "=w,*r")
1363         (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1364    (set (match_operand:SF 2 "register_operand" "=w,*r")
1365         (match_operand:SF 3 "memory_operand" "m,m"))]
1366   "rtx_equal_p (XEXP (operands[3], 0),
1367                 plus_constant (Pmode,
1368                                XEXP (operands[1], 0),
1369                                GET_MODE_SIZE (SFmode)))"
1370   "@
1371    ldp\\t%s0, %s2, %1
1372    ldp\\t%w0, %w2, %1"
1373   [(set_attr "type" "neon_load1_2reg,load2")
1374    (set_attr "fp" "yes,*")]
1377 (define_insn "load_pairdf"
1378   [(set (match_operand:DF 0 "register_operand" "=w,*r")
1379         (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1380    (set (match_operand:DF 2 "register_operand" "=w,*r")
1381         (match_operand:DF 3 "memory_operand" "m,m"))]
1382   "rtx_equal_p (XEXP (operands[3], 0),
1383                 plus_constant (Pmode,
1384                                XEXP (operands[1], 0),
1385                                GET_MODE_SIZE (DFmode)))"
1386   "@
1387    ldp\\t%d0, %d2, %1
1388    ldp\\t%x0, %x2, %1"
1389   [(set_attr "type" "neon_load1_2reg,load2")
1390    (set_attr "fp" "yes,*")]
1393 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1394 ;; fairly lax checking on the second memory operation.
1395 (define_insn "store_pairsf"
1396   [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1397         (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1398    (set (match_operand:SF 2 "memory_operand" "=m,m")
1399         (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1400   "rtx_equal_p (XEXP (operands[2], 0),
1401                 plus_constant (Pmode,
1402                                XEXP (operands[0], 0),
1403                                GET_MODE_SIZE (SFmode)))"
1404   "@
1405    stp\\t%s1, %s3, %0
1406    stp\\t%w1, %w3, %0"
1407   [(set_attr "type" "neon_store1_2reg,store2")
1408    (set_attr "fp" "yes,*")]
1411 (define_insn "store_pairdf"
1412   [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1413         (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1414    (set (match_operand:DF 2 "memory_operand" "=m,m")
1415         (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1416   "rtx_equal_p (XEXP (operands[2], 0),
1417                 plus_constant (Pmode,
1418                                XEXP (operands[0], 0),
1419                                GET_MODE_SIZE (DFmode)))"
1420   "@
1421    stp\\t%d1, %d3, %0
1422    stp\\t%x1, %x3, %0"
1423   [(set_attr "type" "neon_store1_2reg,store2")
1424    (set_attr "fp" "yes,*")]
1427 ;; Load pair with post-index writeback.  This is primarily used in function
1428 ;; epilogues.
1429 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1430   [(parallel
1431     [(set (match_operand:P 0 "register_operand" "=k")
1432           (plus:P (match_operand:P 1 "register_operand" "0")
1433                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1434      (set (match_operand:GPI 2 "register_operand" "=r")
1435           (mem:GPI (match_dup 1)))
1436      (set (match_operand:GPI 3 "register_operand" "=r")
1437           (mem:GPI (plus:P (match_dup 1)
1438                    (match_operand:P 5 "const_int_operand" "n"))))])]
1439   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1440   "ldp\\t%<w>2, %<w>3, [%1], %4"
1441   [(set_attr "type" "load2")]
1444 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1445   [(parallel
1446     [(set (match_operand:P 0 "register_operand" "=k")
1447           (plus:P (match_operand:P 1 "register_operand" "0")
1448                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1449      (set (match_operand:GPF 2 "register_operand" "=w")
1450           (mem:GPF (match_dup 1)))
1451      (set (match_operand:GPF 3 "register_operand" "=w")
1452           (mem:GPF (plus:P (match_dup 1)
1453                    (match_operand:P 5 "const_int_operand" "n"))))])]
1454   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1455   "ldp\\t%<w>2, %<w>3, [%1], %4"
1456   [(set_attr "type" "neon_load1_2reg")]
1459 ;; Store pair with pre-index writeback.  This is primarily used in function
1460 ;; prologues.
1461 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1462   [(parallel
1463     [(set (match_operand:P 0 "register_operand" "=&k")
1464           (plus:P (match_operand:P 1 "register_operand" "0")
1465                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1466      (set (mem:GPI (plus:P (match_dup 0)
1467                    (match_dup 4)))
1468           (match_operand:GPI 2 "register_operand" "r"))
1469      (set (mem:GPI (plus:P (match_dup 0)
1470                    (match_operand:P 5 "const_int_operand" "n")))
1471           (match_operand:GPI 3 "register_operand" "r"))])]
1472   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1473   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1474   [(set_attr "type" "store2")]
1477 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1478   [(parallel
1479     [(set (match_operand:P 0 "register_operand" "=&k")
1480           (plus:P (match_operand:P 1 "register_operand" "0")
1481                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1482      (set (mem:GPF (plus:P (match_dup 0)
1483                    (match_dup 4)))
1484           (match_operand:GPF 2 "register_operand" "w"))
1485      (set (mem:GPF (plus:P (match_dup 0)
1486                    (match_operand:P 5 "const_int_operand" "n")))
1487           (match_operand:GPF 3 "register_operand" "w"))])]
1488   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1489   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1490   [(set_attr "type" "neon_store1_2reg<q>")]
1493 ;; -------------------------------------------------------------------
1494 ;; Sign/Zero extension
1495 ;; -------------------------------------------------------------------
1497 (define_expand "<optab>sidi2"
1498   [(set (match_operand:DI 0 "register_operand")
1499         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1500   ""
1503 (define_insn "*extendsidi2_aarch64"
1504   [(set (match_operand:DI 0 "register_operand" "=r,r")
1505         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1506   ""
1507   "@
1508    sxtw\t%0, %w1
1509    ldrsw\t%0, %1"
1510   [(set_attr "type" "extend,load1")]
1513 (define_insn "*load_pair_extendsidi2_aarch64"
1514   [(set (match_operand:DI 0 "register_operand" "=r")
1515         (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1516    (set (match_operand:DI 2 "register_operand" "=r")
1517         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1518   "rtx_equal_p (XEXP (operands[3], 0),
1519                 plus_constant (Pmode,
1520                                XEXP (operands[1], 0),
1521                                GET_MODE_SIZE (SImode)))"
1522   "ldpsw\\t%0, %2, %1"
1523   [(set_attr "type" "load2")]
1526 (define_insn "*zero_extendsidi2_aarch64"
1527   [(set (match_operand:DI 0 "register_operand" "=r,r")
1528         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1529   ""
1530   "@
1531    uxtw\t%0, %w1
1532    ldr\t%w0, %1"
1533   [(set_attr "type" "extend,load1")]
1536 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1537   [(set (match_operand:DI 0 "register_operand" "=r")
1538         (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1539    (set (match_operand:DI 2 "register_operand" "=r")
1540         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1541   "rtx_equal_p (XEXP (operands[3], 0),
1542                 plus_constant (Pmode,
1543                                XEXP (operands[1], 0),
1544                                GET_MODE_SIZE (SImode)))"
1545   "ldp\\t%w0, %w2, %1"
1546   [(set_attr "type" "load2")]
1549 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1550   [(set (match_operand:GPI 0 "register_operand")
1551         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1552   ""
1555 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1556   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1557         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1558   ""
1559   "@
1560    sxt<SHORT:size>\t%<GPI:w>0, %w1
1561    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1562   [(set_attr "type" "extend,load1")]
1565 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1566   [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1567         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1568   ""
1569   "@
1570    and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1571    ldr<SHORT:size>\t%w0, %1
1572    ldr\t%<SHORT:size>0, %1"
1573   [(set_attr "type" "logic_imm,load1,load1")]
1576 (define_expand "<optab>qihi2"
1577   [(set (match_operand:HI 0 "register_operand")
1578         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1579   ""
1582 (define_insn "*extendqihi2_aarch64"
1583   [(set (match_operand:HI 0 "register_operand" "=r,r")
1584         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1585   ""
1586   "@
1587    sxtb\t%w0, %w1
1588    ldrsb\t%w0, %1"
1589   [(set_attr "type" "extend,load1")]
1592 (define_insn "*zero_extendqihi2_aarch64"
1593   [(set (match_operand:HI 0 "register_operand" "=r,r")
1594         (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1595   ""
1596   "@
1597    and\t%w0, %w1, 255
1598    ldrb\t%w0, %1"
1599   [(set_attr "type" "logic_imm,load1")]
1602 ;; -------------------------------------------------------------------
1603 ;; Simple arithmetic
1604 ;; -------------------------------------------------------------------
1606 (define_expand "add<mode>3"
1607   [(set
1608     (match_operand:GPI 0 "register_operand" "")
1609     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1610               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1611   ""
1613   /* If operands[1] is a subreg extract the inner RTX.  */
1614   rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1616   /* If the constant is too large for a single instruction and isn't frame
1617      based, split off the immediate so it is available for CSE.  */
1618   if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1619       && can_create_pseudo_p ()
1620       && (!REG_P (op1)
1621          || !REGNO_PTR_FRAME_P (REGNO (op1))))
1622     operands[2] = force_reg (<MODE>mode, operands[2]);
1625 (define_insn "*add<mode>3_aarch64"
1626   [(set
1627     (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1628     (plus:GPI
1629      (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1630      (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1631   ""
1632   "@
1633   add\\t%<w>0, %<w>1, %2
1634   add\\t%<w>0, %<w>1, %<w>2
1635   add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1636   sub\\t%<w>0, %<w>1, #%n2
1637   #"
1638   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1639    (set_attr "simd" "*,*,yes,*,*")]
1642 ;; zero_extend version of above
1643 (define_insn "*addsi3_aarch64_uxtw"
1644   [(set
1645     (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1646     (zero_extend:DI
1647      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1648               (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1649   ""
1650   "@
1651   add\\t%w0, %w1, %2
1652   add\\t%w0, %w1, %w2
1653   sub\\t%w0, %w1, #%n2
1654   #"
1655   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1658 ;; If there's a free register, and we can load the constant with a
1659 ;; single instruction, do so.  This has a chance to improve scheduling.
1660 (define_peephole2
1661   [(match_scratch:GPI 3 "r")
1662    (set (match_operand:GPI 0 "register_operand")
1663         (plus:GPI
1664           (match_operand:GPI 1 "register_operand")
1665           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1666   "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1667   [(set (match_dup 3) (match_dup 2))
1668    (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1671 (define_peephole2
1672   [(match_scratch:SI 3 "r")
1673    (set (match_operand:DI 0 "register_operand")
1674         (zero_extend:DI
1675           (plus:SI
1676             (match_operand:SI 1 "register_operand")
1677             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1678   "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1679   [(set (match_dup 3) (match_dup 2))
1680    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1683 ;; After peephole2 has had a chance to run, split any remaining long
1684 ;; additions into two add immediates.
1685 (define_split
1686   [(set (match_operand:GPI 0 "register_operand")
1687         (plus:GPI
1688           (match_operand:GPI 1 "register_operand")
1689           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1690   "epilogue_completed"
1691   [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1692    (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1693   {
1694     HOST_WIDE_INT i = INTVAL (operands[2]);
1695     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1696     operands[3] = GEN_INT (i - s);
1697     operands[4] = GEN_INT (s);
1698   }
1701 (define_split
1702   [(set (match_operand:DI 0 "register_operand")
1703         (zero_extend:DI
1704           (plus:SI
1705             (match_operand:SI 1 "register_operand")
1706             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1707   "epilogue_completed"
1708   [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1709    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1710   {
1711     HOST_WIDE_INT i = INTVAL (operands[2]);
1712     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1713     operands[3] = GEN_INT (i - s);
1714     operands[4] = GEN_INT (s);
1715     operands[5] = gen_lowpart (SImode, operands[0]);
1716   }
1719 (define_expand "addti3"
1720   [(set (match_operand:TI 0 "register_operand" "")
1721         (plus:TI (match_operand:TI 1 "register_operand" "")
1722                  (match_operand:TI 2 "register_operand" "")))]
1723   ""
1725   rtx low = gen_reg_rtx (DImode);
1726   emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1727                                   gen_lowpart (DImode, operands[2])));
1729   rtx high = gen_reg_rtx (DImode);
1730   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1731                                  gen_highpart (DImode, operands[2])));
1733   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1734   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1735   DONE;
1738 (define_insn "add<mode>3_compare0"
1739   [(set (reg:CC_NZ CC_REGNUM)
1740         (compare:CC_NZ
1741          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1742                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1743          (const_int 0)))
1744    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1745         (plus:GPI (match_dup 1) (match_dup 2)))]
1746   ""
1747   "@
1748   adds\\t%<w>0, %<w>1, %<w>2
1749   adds\\t%<w>0, %<w>1, %2
1750   subs\\t%<w>0, %<w>1, #%n2"
1751   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1754 ;; zero_extend version of above
1755 (define_insn "*addsi3_compare0_uxtw"
1756   [(set (reg:CC_NZ CC_REGNUM)
1757         (compare:CC_NZ
1758          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1759                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1760          (const_int 0)))
1761    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1762         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1763   ""
1764   "@
1765   adds\\t%w0, %w1, %w2
1766   adds\\t%w0, %w1, %2
1767   subs\\t%w0, %w1, #%n2"
1768   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1771 (define_insn "*add<mode>3_compareC_cconly_imm"
1772   [(set (reg:CC_C CC_REGNUM)
1773         (ne:CC_C
1774           (plus:<DWI>
1775             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1776             (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1777           (zero_extend:<DWI>
1778             (plus:GPI
1779               (match_dup 0)
1780               (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1781   "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1782                                  <MODE>mode, operands[1])"
1783   "@
1784   cmn\\t%<w>0, %1
1785   cmp\\t%<w>0, #%n1"
1786   [(set_attr "type" "alus_imm")]
1789 (define_insn "*add<mode>3_compareC_cconly"
1790   [(set (reg:CC_C CC_REGNUM)
1791         (ne:CC_C
1792           (plus:<DWI>
1793             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1794             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1795           (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1796   ""
1797   "cmn\\t%<w>0, %<w>1"
1798   [(set_attr "type" "alus_sreg")]
1801 (define_insn "*add<mode>3_compareC_imm"
1802   [(set (reg:CC_C CC_REGNUM)
1803         (ne:CC_C
1804           (plus:<DWI>
1805             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1806             (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1807           (zero_extend:<DWI>
1808             (plus:GPI
1809               (match_dup 1)
1810               (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1811    (set (match_operand:GPI 0 "register_operand" "=r,r")
1812         (plus:GPI (match_dup 1) (match_dup 2)))]
1813   "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1814                                  <MODE>mode, operands[2])"
1815   "@
1816   adds\\t%<w>0, %<w>1, %2
1817   subs\\t%<w>0, %<w>1, #%n2"
1818   [(set_attr "type" "alus_imm")]
1821 (define_insn "add<mode>3_compareC"
1822   [(set (reg:CC_C CC_REGNUM)
1823         (ne:CC_C
1824           (plus:<DWI>
1825             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1826             (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1827           (zero_extend:<DWI>
1828             (plus:GPI (match_dup 1) (match_dup 2)))))
1829    (set (match_operand:GPI 0 "register_operand" "=r")
1830         (plus:GPI (match_dup 1) (match_dup 2)))]
1831   ""
1832   "adds\\t%<w>0, %<w>1, %<w>2"
1833   [(set_attr "type" "alus_sreg")]
1836 (define_insn "*adds_shift_imm_<mode>"
1837   [(set (reg:CC_NZ CC_REGNUM)
1838         (compare:CC_NZ
1839          (plus:GPI (ASHIFT:GPI 
1840                     (match_operand:GPI 1 "register_operand" "r")
1841                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1842                    (match_operand:GPI 3 "register_operand" "r"))
1843          (const_int 0)))
1844    (set (match_operand:GPI 0 "register_operand" "=r")
1845         (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1846                   (match_dup 3)))]
1847   ""
1848   "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1849   [(set_attr "type" "alus_shift_imm")]
1852 (define_insn "*subs_shift_imm_<mode>"
1853   [(set (reg:CC_NZ CC_REGNUM)
1854         (compare:CC_NZ
1855          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1856                     (ASHIFT:GPI
1857                      (match_operand:GPI 2 "register_operand" "r")
1858                      (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1859          (const_int 0)))
1860    (set (match_operand:GPI 0 "register_operand" "=r")
1861         (minus:GPI (match_dup 1)
1862                    (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1863   ""
1864   "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1865   [(set_attr "type" "alus_shift_imm")]
1868 (define_insn "*adds_mul_imm_<mode>"
1869   [(set (reg:CC_NZ CC_REGNUM)
1870         (compare:CC_NZ
1871          (plus:GPI (mult:GPI
1872                     (match_operand:GPI 1 "register_operand" "r")
1873                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1874                    (match_operand:GPI 3 "register_operand" "r"))
1875          (const_int 0)))
1876    (set (match_operand:GPI 0 "register_operand" "=r")
1877         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1878                   (match_dup 3)))]
1879   ""
1880   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1881   [(set_attr "type" "alus_shift_imm")]
1884 (define_insn "*subs_mul_imm_<mode>"
1885   [(set (reg:CC_NZ CC_REGNUM)
1886         (compare:CC_NZ
1887          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1888                     (mult:GPI
1889                      (match_operand:GPI 2 "register_operand" "r")
1890                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1891          (const_int 0)))
1892    (set (match_operand:GPI 0 "register_operand" "=r")
1893         (minus:GPI (match_dup 1)
1894                    (mult:GPI (match_dup 2) (match_dup 3))))]
1895   ""
1896   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1897   [(set_attr "type" "alus_shift_imm")]
1900 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1901   [(set (reg:CC_NZ CC_REGNUM)
1902         (compare:CC_NZ
1903          (plus:GPI
1904           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1905           (match_operand:GPI 2 "register_operand" "r"))
1906         (const_int 0)))
1907    (set (match_operand:GPI 0 "register_operand" "=r")
1908         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1909   ""
1910   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1911   [(set_attr "type" "alus_ext")]
1914 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1915   [(set (reg:CC_NZ CC_REGNUM)
1916         (compare:CC_NZ
1917          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1918                     (ANY_EXTEND:GPI
1919                      (match_operand:ALLX 2 "register_operand" "r")))
1920         (const_int 0)))
1921    (set (match_operand:GPI 0 "register_operand" "=r")
1922         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1923   ""
1924   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1925   [(set_attr "type" "alus_ext")]
1928 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1929   [(set (reg:CC_NZ CC_REGNUM)
1930         (compare:CC_NZ
1931          (plus:GPI (ashift:GPI 
1932                     (ANY_EXTEND:GPI 
1933                      (match_operand:ALLX 1 "register_operand" "r"))
1934                     (match_operand 2 "aarch64_imm3" "Ui3"))
1935                    (match_operand:GPI 3 "register_operand" "r"))
1936          (const_int 0)))
1937    (set (match_operand:GPI 0 "register_operand" "=rk")
1938         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1939                               (match_dup 2))
1940                   (match_dup 3)))]
1941   ""
1942   "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1943   [(set_attr "type" "alus_ext")]
1946 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1947   [(set (reg:CC_NZ CC_REGNUM)
1948         (compare:CC_NZ
1949          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1950                     (ashift:GPI 
1951                      (ANY_EXTEND:GPI
1952                       (match_operand:ALLX 2 "register_operand" "r"))
1953                      (match_operand 3 "aarch64_imm3" "Ui3")))
1954          (const_int 0)))
1955    (set (match_operand:GPI 0 "register_operand" "=rk")
1956         (minus:GPI (match_dup 1)
1957                    (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1958                                (match_dup 3))))]
1959   ""
1960   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1961   [(set_attr "type" "alus_ext")]
1964 (define_insn "*adds_<optab><mode>_multp2"
1965   [(set (reg:CC_NZ CC_REGNUM)
1966         (compare:CC_NZ
1967          (plus:GPI (ANY_EXTRACT:GPI
1968                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1969                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1970                     (match_operand 3 "const_int_operand" "n")
1971                     (const_int 0))
1972                    (match_operand:GPI 4 "register_operand" "r"))
1973         (const_int 0)))
1974    (set (match_operand:GPI 0 "register_operand" "=r")
1975         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1976                                    (match_dup 3)
1977                                    (const_int 0))
1978                   (match_dup 4)))]
1979   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1980   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1981   [(set_attr "type" "alus_ext")]
1984 (define_insn "*subs_<optab><mode>_multp2"
1985   [(set (reg:CC_NZ CC_REGNUM)
1986         (compare:CC_NZ
1987          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1988                     (ANY_EXTRACT:GPI
1989                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1990                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1991                      (match_operand 3 "const_int_operand" "n")
1992                      (const_int 0)))
1993         (const_int 0)))
1994    (set (match_operand:GPI 0 "register_operand" "=r")
1995         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1996                                   (mult:GPI (match_dup 1) (match_dup 2))
1997                                   (match_dup 3)
1998                                   (const_int 0))))]
1999   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2000   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2001   [(set_attr "type" "alus_ext")]
2004 (define_insn "*add<mode>3nr_compare0"
2005   [(set (reg:CC_NZ CC_REGNUM)
2006         (compare:CC_NZ
2007          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2008                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2009          (const_int 0)))]
2010   ""
2011   "@
2012   cmn\\t%<w>0, %<w>1
2013   cmn\\t%<w>0, %1
2014   cmp\\t%<w>0, #%n1"
2015   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2018 (define_insn "*compare_neg<mode>"
2019   [(set (reg:CC_Z CC_REGNUM)
2020         (compare:CC_Z
2021          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2022          (match_operand:GPI 1 "register_operand" "r")))]
2023   ""
2024   "cmn\\t%<w>1, %<w>0"
2025   [(set_attr "type" "alus_sreg")]
2028 (define_insn "*add_<shift>_<mode>"
2029   [(set (match_operand:GPI 0 "register_operand" "=r")
2030         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2031                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2032                   (match_operand:GPI 3 "register_operand" "r")))]
2033   ""
2034   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2035   [(set_attr "type" "alu_shift_imm")]
2038 ;; zero_extend version of above
2039 (define_insn "*add_<shift>_si_uxtw"
2040   [(set (match_operand:DI 0 "register_operand" "=r")
2041         (zero_extend:DI
2042          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2043                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2044                   (match_operand:SI 3 "register_operand" "r"))))]
2045   ""
2046   "add\\t%w0, %w3, %w1, <shift> %2"
2047   [(set_attr "type" "alu_shift_imm")]
2050 (define_insn "*add_mul_imm_<mode>"
2051   [(set (match_operand:GPI 0 "register_operand" "=r")
2052         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2053                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2054                   (match_operand:GPI 3 "register_operand" "r")))]
2055   ""
2056   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2057   [(set_attr "type" "alu_shift_imm")]
2060 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2061   [(set (match_operand:GPI 0 "register_operand" "=rk")
2062         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2063                   (match_operand:GPI 2 "register_operand" "r")))]
2064   ""
2065   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2066   [(set_attr "type" "alu_ext")]
2069 ;; zero_extend version of above
2070 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2071   [(set (match_operand:DI 0 "register_operand" "=rk")
2072         (zero_extend:DI
2073          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2074                   (match_operand:GPI 2 "register_operand" "r"))))]
2075   ""
2076   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2077   [(set_attr "type" "alu_ext")]
2080 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2081   [(set (match_operand:GPI 0 "register_operand" "=rk")
2082         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2083                                (match_operand:ALLX 1 "register_operand" "r"))
2084                               (match_operand 2 "aarch64_imm3" "Ui3"))
2085                   (match_operand:GPI 3 "register_operand" "r")))]
2086   ""
2087   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2088   [(set_attr "type" "alu_ext")]
2091 ;; zero_extend version of above
2092 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2093   [(set (match_operand:DI 0 "register_operand" "=rk")
2094         (zero_extend:DI
2095          (plus:SI (ashift:SI (ANY_EXTEND:SI
2096                               (match_operand:SHORT 1 "register_operand" "r"))
2097                              (match_operand 2 "aarch64_imm3" "Ui3"))
2098                   (match_operand:SI 3 "register_operand" "r"))))]
2099   ""
2100   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2101   [(set_attr "type" "alu_ext")]
2104 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2105   [(set (match_operand:GPI 0 "register_operand" "=rk")
2106         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2107                              (match_operand:ALLX 1 "register_operand" "r"))
2108                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2109                   (match_operand:GPI 3 "register_operand" "r")))]
2110   ""
2111   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2112   [(set_attr "type" "alu_ext")]
2115 ;; zero_extend version of above
2116 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2117   [(set (match_operand:DI 0 "register_operand" "=rk")
2118         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2119                              (match_operand:SHORT 1 "register_operand" "r"))
2120                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2121                   (match_operand:SI 3 "register_operand" "r"))))]
2122   ""
2123   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2124   [(set_attr "type" "alu_ext")]
2127 (define_insn "*add_<optab><mode>_multp2"
2128   [(set (match_operand:GPI 0 "register_operand" "=rk")
2129         (plus:GPI (ANY_EXTRACT:GPI
2130                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2131                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2132                    (match_operand 3 "const_int_operand" "n")
2133                    (const_int 0))
2134                   (match_operand:GPI 4 "register_operand" "r")))]
2135   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2136   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2137   [(set_attr "type" "alu_ext")]
2140 ;; zero_extend version of above
2141 (define_insn "*add_<optab>si_multp2_uxtw"
2142   [(set (match_operand:DI 0 "register_operand" "=rk")
2143         (zero_extend:DI
2144          (plus:SI (ANY_EXTRACT:SI
2145                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2146                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2147                    (match_operand 3 "const_int_operand" "n")
2148                    (const_int 0))
2149                   (match_operand:SI 4 "register_operand" "r"))))]
2150   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2151   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2152   [(set_attr "type" "alu_ext")]
2155 (define_expand "add<mode>3_carryin"
2156   [(set (match_operand:GPI 0 "register_operand")
2157         (plus:GPI
2158           (plus:GPI
2159             (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2160             (match_operand:GPI 1 "aarch64_reg_or_zero"))
2161           (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2162    ""
2163    ""
2166 ;; Note that add with carry with two zero inputs is matched by cset,
2167 ;; and that add with carry with one zero input is matched by cinc.
2169 (define_insn "*add<mode>3_carryin"
2170   [(set (match_operand:GPI 0 "register_operand" "=r")
2171         (plus:GPI
2172           (plus:GPI
2173             (match_operand:GPI 3 "aarch64_carry_operation" "")
2174             (match_operand:GPI 1 "register_operand" "r"))
2175           (match_operand:GPI 2 "register_operand" "r")))]
2176    ""
2177    "adc\\t%<w>0, %<w>1, %<w>2"
2178   [(set_attr "type" "adc_reg")]
2181 ;; zero_extend version of above
2182 (define_insn "*addsi3_carryin_uxtw"
2183   [(set (match_operand:DI 0 "register_operand" "=r")
2184         (zero_extend:DI
2185           (plus:SI
2186             (plus:SI
2187               (match_operand:SI 3 "aarch64_carry_operation" "")
2188               (match_operand:SI 1 "register_operand" "r"))
2189             (match_operand:SI 2 "register_operand" "r"))))]
2190    ""
2191    "adc\\t%w0, %w1, %w2"
2192   [(set_attr "type" "adc_reg")]
2195 (define_insn "*add_uxt<mode>_shift2"
2196   [(set (match_operand:GPI 0 "register_operand" "=rk")
2197         (plus:GPI (and:GPI
2198                    (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2199                                (match_operand 2 "aarch64_imm3" "Ui3"))
2200                    (match_operand 3 "const_int_operand" "n"))
2201                   (match_operand:GPI 4 "register_operand" "r")))]
2202   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2203   "*
2204   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2205                                            INTVAL (operands[3])));
2206   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2207   [(set_attr "type" "alu_ext")]
2210 ;; zero_extend version of above
2211 (define_insn "*add_uxtsi_shift2_uxtw"
2212   [(set (match_operand:DI 0 "register_operand" "=rk")
2213         (zero_extend:DI
2214          (plus:SI (and:SI
2215                    (ashift:SI (match_operand:SI 1 "register_operand" "r")
2216                               (match_operand 2 "aarch64_imm3" "Ui3"))
2217                    (match_operand 3 "const_int_operand" "n"))
2218                   (match_operand:SI 4 "register_operand" "r"))))]
2219   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2220   "*
2221   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2222                                            INTVAL (operands[3])));
2223   return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2224   [(set_attr "type" "alu_ext")]
2227 (define_insn "*add_uxt<mode>_multp2"
2228   [(set (match_operand:GPI 0 "register_operand" "=rk")
2229         (plus:GPI (and:GPI
2230                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2231                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2232                    (match_operand 3 "const_int_operand" "n"))
2233                   (match_operand:GPI 4 "register_operand" "r")))]
2234   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2235   "*
2236   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2237                                            INTVAL (operands[3])));
2238   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2239   [(set_attr "type" "alu_ext")]
2242 ;; zero_extend version of above
2243 (define_insn "*add_uxtsi_multp2_uxtw"
2244   [(set (match_operand:DI 0 "register_operand" "=rk")
2245         (zero_extend:DI
2246          (plus:SI (and:SI
2247                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2248                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2249                    (match_operand 3 "const_int_operand" "n"))
2250                   (match_operand:SI 4 "register_operand" "r"))))]
2251   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2252   "*
2253   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2254                                            INTVAL (operands[3])));
2255   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2256   [(set_attr "type" "alu_ext")]
2259 (define_insn "subsi3"
2260   [(set (match_operand:SI 0 "register_operand" "=rk")
2261         (minus:SI (match_operand:SI 1 "register_operand" "rk")
2262                   (match_operand:SI 2 "register_operand" "r")))]
2263   ""
2264   "sub\\t%w0, %w1, %w2"
2265   [(set_attr "type" "alu_sreg")]
2268 ;; zero_extend version of above
2269 (define_insn "*subsi3_uxtw"
2270   [(set (match_operand:DI 0 "register_operand" "=rk")
2271         (zero_extend:DI
2272          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2273                    (match_operand:SI 2 "register_operand" "r"))))]
2274   ""
2275   "sub\\t%w0, %w1, %w2"
2276   [(set_attr "type" "alu_sreg")]
2279 (define_insn "subdi3"
2280   [(set (match_operand:DI 0 "register_operand" "=rk,w")
2281         (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2282                   (match_operand:DI 2 "register_operand" "r,w")))]
2283   ""
2284   "@
2285    sub\\t%x0, %x1, %x2
2286    sub\\t%d0, %d1, %d2"
2287   [(set_attr "type" "alu_sreg, neon_sub")
2288    (set_attr "simd" "*,yes")]
2291 (define_expand "subti3"
2292   [(set (match_operand:TI 0 "register_operand" "")
2293         (minus:TI (match_operand:TI 1 "register_operand" "")
2294                   (match_operand:TI 2 "register_operand" "")))]
2295   ""
2297   rtx low = gen_reg_rtx (DImode);
2298   emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2299                                   gen_lowpart (DImode, operands[2])));
2301   rtx high = gen_reg_rtx (DImode);
2302   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2303                                  gen_highpart (DImode, operands[2])));
2305   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2306   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2307   DONE;
2310 (define_insn "*sub<mode>3_compare0"
2311   [(set (reg:CC_NZ CC_REGNUM)
2312         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2313                                   (match_operand:GPI 2 "register_operand" "r"))
2314                        (const_int 0)))
2315    (set (match_operand:GPI 0 "register_operand" "=r")
2316         (minus:GPI (match_dup 1) (match_dup 2)))]
2317   ""
2318   "subs\\t%<w>0, %<w>1, %<w>2"
2319   [(set_attr "type" "alus_sreg")]
2322 ;; zero_extend version of above
2323 (define_insn "*subsi3_compare0_uxtw"
2324   [(set (reg:CC_NZ CC_REGNUM)
2325         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2326                                  (match_operand:SI 2 "register_operand" "r"))
2327                        (const_int 0)))
2328    (set (match_operand:DI 0 "register_operand" "=r")
2329         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2330   ""
2331   "subs\\t%w0, %w1, %w2"
2332   [(set_attr "type" "alus_sreg")]
2335 (define_insn "sub<mode>3_compare1"
2336   [(set (reg:CC CC_REGNUM)
2337         (compare:CC
2338           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2339           (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2340    (set (match_operand:GPI 0 "register_operand" "=r")
2341         (minus:GPI (match_dup 1) (match_dup 2)))]
2342   ""
2343   "subs\\t%<w>0, %<w>1, %<w>2"
2344   [(set_attr "type" "alus_sreg")]
2347 (define_insn "*sub_<shift>_<mode>"
2348   [(set (match_operand:GPI 0 "register_operand" "=r")
2349         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2350                    (ASHIFT:GPI
2351                     (match_operand:GPI 1 "register_operand" "r")
2352                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2353   ""
2354   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2355   [(set_attr "type" "alu_shift_imm")]
2358 ;; zero_extend version of above
2359 (define_insn "*sub_<shift>_si_uxtw"
2360   [(set (match_operand:DI 0 "register_operand" "=r")
2361         (zero_extend:DI
2362          (minus:SI (match_operand:SI 3 "register_operand" "r")
2363                    (ASHIFT:SI
2364                     (match_operand:SI 1 "register_operand" "r")
2365                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2366   ""
2367   "sub\\t%w0, %w3, %w1, <shift> %2"
2368   [(set_attr "type" "alu_shift_imm")]
2371 (define_insn "*sub_mul_imm_<mode>"
2372   [(set (match_operand:GPI 0 "register_operand" "=r")
2373         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2374                    (mult:GPI
2375                     (match_operand:GPI 1 "register_operand" "r")
2376                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2377   ""
2378   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2379   [(set_attr "type" "alu_shift_imm")]
2382 ;; zero_extend version of above
2383 (define_insn "*sub_mul_imm_si_uxtw"
2384   [(set (match_operand:DI 0 "register_operand" "=r")
2385         (zero_extend:DI
2386          (minus:SI (match_operand:SI 3 "register_operand" "r")
2387                    (mult:SI
2388                     (match_operand:SI 1 "register_operand" "r")
2389                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2390   ""
2391   "sub\\t%w0, %w3, %w1, lsl %p2"
2392   [(set_attr "type" "alu_shift_imm")]
2395 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2396   [(set (match_operand:GPI 0 "register_operand" "=rk")
2397         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2398                    (ANY_EXTEND:GPI
2399                     (match_operand:ALLX 2 "register_operand" "r"))))]
2400   ""
2401   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2402   [(set_attr "type" "alu_ext")]
2405 ;; zero_extend version of above
2406 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2407   [(set (match_operand:DI 0 "register_operand" "=rk")
2408         (zero_extend:DI
2409          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2410                    (ANY_EXTEND:SI
2411                     (match_operand:SHORT 2 "register_operand" "r")))))]
2412   ""
2413   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2414   [(set_attr "type" "alu_ext")]
2417 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2418   [(set (match_operand:GPI 0 "register_operand" "=rk")
2419         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2420                    (ashift:GPI (ANY_EXTEND:GPI
2421                                 (match_operand:ALLX 2 "register_operand" "r"))
2422                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
2423   ""
2424   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2425   [(set_attr "type" "alu_ext")]
2428 ;; zero_extend version of above
2429 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2430   [(set (match_operand:DI 0 "register_operand" "=rk")
2431         (zero_extend:DI
2432          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2433                    (ashift:SI (ANY_EXTEND:SI
2434                                (match_operand:SHORT 2 "register_operand" "r"))
2435                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
2436   ""
2437   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2438   [(set_attr "type" "alu_ext")]
2441 (define_insn "*sub_<optab><mode>_multp2"
2442   [(set (match_operand:GPI 0 "register_operand" "=rk")
2443         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2444                    (ANY_EXTRACT:GPI
2445                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2446                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2447                     (match_operand 3 "const_int_operand" "n")
2448                     (const_int 0))))]
2449   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2450   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2451   [(set_attr "type" "alu_ext")]
2454 ;; zero_extend version of above
2455 (define_insn "*sub_<optab>si_multp2_uxtw"
2456   [(set (match_operand:DI 0 "register_operand" "=rk")
2457         (zero_extend:DI
2458          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2459                    (ANY_EXTRACT:SI
2460                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2461                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2462                     (match_operand 3 "const_int_operand" "n")
2463                     (const_int 0)))))]
2464   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2465   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2466   [(set_attr "type" "alu_ext")]
2469 ;; The hardware description is op1 + ~op2 + C.
2470 ;;                           = op1 + (-op2 + 1) + (1 - !C)
2471 ;;                           = op1 - op2 - 1 + 1 - !C
2472 ;;                           = op1 - op2 - !C.
2473 ;; We describe the latter.
2475 (define_insn "*sub<mode>3_carryin0"
2476   [(set (match_operand:GPI 0 "register_operand" "=r")
2477         (minus:GPI
2478           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2479           (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2480    ""
2481    "sbc\\t%<w>0, %<w>1, <w>zr"
2482   [(set_attr "type" "adc_reg")]
2485 ;; zero_extend version of the above
2486 (define_insn "*subsi3_carryin_uxtw"
2487   [(set (match_operand:DI 0 "register_operand" "=r")
2488         (zero_extend:DI
2489           (minus:SI
2490             (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2491             (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2492    ""
2493    "sbc\\t%w0, %w1, wzr"
2494   [(set_attr "type" "adc_reg")]
2497 (define_expand "sub<mode>3_carryin"
2498   [(set (match_operand:GPI 0 "register_operand")
2499         (minus:GPI
2500           (minus:GPI
2501             (match_operand:GPI 1 "aarch64_reg_or_zero")
2502             (match_operand:GPI 2 "register_operand"))
2503           (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2504    ""
2505    ""
2508 (define_insn "*sub<mode>3_carryin"
2509   [(set (match_operand:GPI 0 "register_operand" "=r")
2510         (minus:GPI
2511           (minus:GPI
2512             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2513             (match_operand:GPI 2 "register_operand" "r"))
2514           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2516    ""
2517    "sbc\\t%<w>0, %<w>1, %<w>2"
2518   [(set_attr "type" "adc_reg")]
2521 ;; zero_extend version of the above
2522 (define_insn "*subsi3_carryin_uxtw"
2523   [(set (match_operand:DI 0 "register_operand" "=r")
2524         (zero_extend:DI
2525           (minus:SI
2526             (minus:SI
2527               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2528               (match_operand:SI 2 "register_operand" "r"))
2529             (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2531    ""
2532    "sbc\\t%w0, %w1, %w2"
2533   [(set_attr "type" "adc_reg")]
2536 (define_insn "*sub<mode>3_carryin_alt"
2537   [(set (match_operand:GPI 0 "register_operand" "=r")
2538         (minus:GPI
2539           (minus:GPI
2540             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2541             (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2542           (match_operand:GPI 2 "register_operand" "r")))]
2543    ""
2544    "sbc\\t%<w>0, %<w>1, %<w>2"
2545   [(set_attr "type" "adc_reg")]
2548 ;; zero_extend version of the above
2549 (define_insn "*subsi3_carryin_alt_uxtw"
2550   [(set (match_operand:DI 0 "register_operand" "=r")
2551         (zero_extend:DI
2552           (minus:SI
2553             (minus:SI
2554               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2555               (match_operand:SI 3 "aarch64_borrow_operation" ""))
2556             (match_operand:SI 2 "register_operand" "r"))))]
2557    ""
2558    "sbc\\t%w0, %w1, %w2"
2559   [(set_attr "type" "adc_reg")]
2562 (define_insn "*sub_uxt<mode>_shift2"
2563   [(set (match_operand:GPI 0 "register_operand" "=rk")
2564         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2565                    (and:GPI
2566                     (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2567                                 (match_operand 2 "aarch64_imm3" "Ui3"))
2568                     (match_operand 3 "const_int_operand" "n"))))]
2569   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2570   "*
2571   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2572                                            INTVAL (operands[3])));
2573   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2574   [(set_attr "type" "alu_ext")]
2577 ;; zero_extend version of above
2578 (define_insn "*sub_uxtsi_shift2_uxtw"
2579   [(set (match_operand:DI 0 "register_operand" "=rk")
2580         (zero_extend:DI
2581          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2582                    (and:SI
2583                     (ashift:SI (match_operand:SI 1 "register_operand" "r")
2584                                (match_operand 2 "aarch64_imm3" "Ui3"))
2585                     (match_operand 3 "const_int_operand" "n")))))]
2586   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2587   "*
2588   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2589                                            INTVAL (operands[3])));
2590   return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2591   [(set_attr "type" "alu_ext")]
2594 (define_insn "*sub_uxt<mode>_multp2"
2595   [(set (match_operand:GPI 0 "register_operand" "=rk")
2596         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2597                    (and:GPI
2598                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2599                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2600                     (match_operand 3 "const_int_operand" "n"))))]
2601   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2602   "*
2603   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2604                                            INTVAL (operands[3])));
2605   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2606   [(set_attr "type" "alu_ext")]
2609 ;; zero_extend version of above
2610 (define_insn "*sub_uxtsi_multp2_uxtw"
2611   [(set (match_operand:DI 0 "register_operand" "=rk")
2612         (zero_extend:DI
2613          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2614                    (and:SI
2615                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2616                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2617                     (match_operand 3 "const_int_operand" "n")))))]
2618   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2619   "*
2620   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2621                                            INTVAL (operands[3])));
2622   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2623   [(set_attr "type" "alu_ext")]
2626 (define_expand "abs<mode>2"
2627   [(match_operand:GPI 0 "register_operand" "")
2628    (match_operand:GPI 1 "register_operand" "")]
2629   ""
2630   {
2631     rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2632     rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2633     emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2634     DONE;
2635   }
2638 (define_insn "neg<mode>2"
2639   [(set (match_operand:GPI 0 "register_operand" "=r,w")
2640         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2641   ""
2642   "@
2643    neg\\t%<w>0, %<w>1
2644    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2645   [(set_attr "type" "alu_sreg, neon_neg<q>")
2646    (set_attr "simd" "*,yes")]
2649 ;; zero_extend version of above
2650 (define_insn "*negsi2_uxtw"
2651   [(set (match_operand:DI 0 "register_operand" "=r")
2652         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2653   ""
2654   "neg\\t%w0, %w1"
2655   [(set_attr "type" "alu_sreg")]
2658 (define_insn "*ngc<mode>"
2659   [(set (match_operand:GPI 0 "register_operand" "=r")
2660         (minus:GPI
2661           (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2662           (match_operand:GPI 1 "register_operand" "r")))]
2663   ""
2664   "ngc\\t%<w>0, %<w>1"
2665   [(set_attr "type" "adc_reg")]
2668 (define_insn "*ngcsi_uxtw"
2669   [(set (match_operand:DI 0 "register_operand" "=r")
2670         (zero_extend:DI
2671           (minus:SI
2672             (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2673             (match_operand:SI 1 "register_operand" "r"))))]
2674   ""
2675   "ngc\\t%w0, %w1"
2676   [(set_attr "type" "adc_reg")]
2679 (define_insn "neg<mode>2_compare0"
2680   [(set (reg:CC_NZ CC_REGNUM)
2681         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2682                        (const_int 0)))
2683    (set (match_operand:GPI 0 "register_operand" "=r")
2684         (neg:GPI (match_dup 1)))]
2685   ""
2686   "negs\\t%<w>0, %<w>1"
2687   [(set_attr "type" "alus_sreg")]
2690 ;; zero_extend version of above
2691 (define_insn "*negsi2_compare0_uxtw"
2692   [(set (reg:CC_NZ CC_REGNUM)
2693         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2694                        (const_int 0)))
2695    (set (match_operand:DI 0 "register_operand" "=r")
2696         (zero_extend:DI (neg:SI (match_dup 1))))]
2697   ""
2698   "negs\\t%w0, %w1"
2699   [(set_attr "type" "alus_sreg")]
2702 (define_insn "*neg_<shift><mode>3_compare0"
2703   [(set (reg:CC_NZ CC_REGNUM)
2704         (compare:CC_NZ
2705          (neg:GPI (ASHIFT:GPI
2706                    (match_operand:GPI 1 "register_operand" "r")
2707                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2708          (const_int 0)))
2709    (set (match_operand:GPI 0 "register_operand" "=r")
2710         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2711   ""
2712   "negs\\t%<w>0, %<w>1, <shift> %2"
2713   [(set_attr "type" "alus_shift_imm")]
2716 (define_insn "*neg_<shift>_<mode>2"
2717   [(set (match_operand:GPI 0 "register_operand" "=r")
2718         (neg:GPI (ASHIFT:GPI
2719                   (match_operand:GPI 1 "register_operand" "r")
2720                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2721   ""
2722   "neg\\t%<w>0, %<w>1, <shift> %2"
2723   [(set_attr "type" "alu_shift_imm")]
2726 ;; zero_extend version of above
2727 (define_insn "*neg_<shift>_si2_uxtw"
2728   [(set (match_operand:DI 0 "register_operand" "=r")
2729         (zero_extend:DI
2730          (neg:SI (ASHIFT:SI
2731                   (match_operand:SI 1 "register_operand" "r")
2732                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2733   ""
2734   "neg\\t%w0, %w1, <shift> %2"
2735   [(set_attr "type" "alu_shift_imm")]
2738 (define_insn "*neg_mul_imm_<mode>2"
2739   [(set (match_operand:GPI 0 "register_operand" "=r")
2740         (neg:GPI (mult:GPI
2741                   (match_operand:GPI 1 "register_operand" "r")
2742                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2743   ""
2744   "neg\\t%<w>0, %<w>1, lsl %p2"
2745   [(set_attr "type" "alu_shift_imm")]
2748 ;; zero_extend version of above
2749 (define_insn "*neg_mul_imm_si2_uxtw"
2750   [(set (match_operand:DI 0 "register_operand" "=r")
2751         (zero_extend:DI
2752          (neg:SI (mult:SI
2753                   (match_operand:SI 1 "register_operand" "r")
2754                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2755   ""
2756   "neg\\t%w0, %w1, lsl %p2"
2757   [(set_attr "type" "alu_shift_imm")]
2760 (define_insn "mul<mode>3"
2761   [(set (match_operand:GPI 0 "register_operand" "=r")
2762         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2763                   (match_operand:GPI 2 "register_operand" "r")))]
2764   ""
2765   "mul\\t%<w>0, %<w>1, %<w>2"
2766   [(set_attr "type" "mul")]
2769 ;; zero_extend version of above
2770 (define_insn "*mulsi3_uxtw"
2771   [(set (match_operand:DI 0 "register_operand" "=r")
2772         (zero_extend:DI
2773          (mult:SI (match_operand:SI 1 "register_operand" "r")
2774                   (match_operand:SI 2 "register_operand" "r"))))]
2775   ""
2776   "mul\\t%w0, %w1, %w2"
2777   [(set_attr "type" "mul")]
2780 (define_insn "madd<mode>"
2781   [(set (match_operand:GPI 0 "register_operand" "=r")
2782         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2783                             (match_operand:GPI 2 "register_operand" "r"))
2784                   (match_operand:GPI 3 "register_operand" "r")))]
2785   ""
2786   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2787   [(set_attr "type" "mla")]
2790 ;; zero_extend version of above
2791 (define_insn "*maddsi_uxtw"
2792   [(set (match_operand:DI 0 "register_operand" "=r")
2793         (zero_extend:DI
2794          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2795                            (match_operand:SI 2 "register_operand" "r"))
2796                   (match_operand:SI 3 "register_operand" "r"))))]
2797   ""
2798   "madd\\t%w0, %w1, %w2, %w3"
2799   [(set_attr "type" "mla")]
2802 (define_insn "*msub<mode>"
2803   [(set (match_operand:GPI 0 "register_operand" "=r")
2804         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2805                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2806                              (match_operand:GPI 2 "register_operand" "r"))))]
2808   ""
2809   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2810   [(set_attr "type" "mla")]
2813 ;; zero_extend version of above
2814 (define_insn "*msubsi_uxtw"
2815   [(set (match_operand:DI 0 "register_operand" "=r")
2816         (zero_extend:DI
2817          (minus:SI (match_operand:SI 3 "register_operand" "r")
2818                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2819                             (match_operand:SI 2 "register_operand" "r")))))]
2821   ""
2822   "msub\\t%w0, %w1, %w2, %w3"
2823   [(set_attr "type" "mla")]
2826 (define_insn "*mul<mode>_neg"
2827   [(set (match_operand:GPI 0 "register_operand" "=r")
2828         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2829                   (match_operand:GPI 2 "register_operand" "r")))]
2831   ""
2832   "mneg\\t%<w>0, %<w>1, %<w>2"
2833   [(set_attr "type" "mul")]
2836 ;; zero_extend version of above
2837 (define_insn "*mulsi_neg_uxtw"
2838   [(set (match_operand:DI 0 "register_operand" "=r")
2839         (zero_extend:DI
2840          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2841                   (match_operand:SI 2 "register_operand" "r"))))]
2843   ""
2844   "mneg\\t%w0, %w1, %w2"
2845   [(set_attr "type" "mul")]
2848 (define_insn "<su_optab>mulsidi3"
2849   [(set (match_operand:DI 0 "register_operand" "=r")
2850         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2851                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2852   ""
2853   "<su>mull\\t%0, %w1, %w2"
2854   [(set_attr "type" "<su>mull")]
2857 (define_insn "<su_optab>maddsidi4"
2858   [(set (match_operand:DI 0 "register_operand" "=r")
2859         (plus:DI (mult:DI
2860                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2861                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2862                  (match_operand:DI 3 "register_operand" "r")))]
2863   ""
2864   "<su>maddl\\t%0, %w1, %w2, %3"
2865   [(set_attr "type" "<su>mlal")]
2868 (define_insn "<su_optab>msubsidi4"
2869   [(set (match_operand:DI 0 "register_operand" "=r")
2870         (minus:DI
2871          (match_operand:DI 3 "register_operand" "r")
2872          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2873                   (ANY_EXTEND:DI
2874                    (match_operand:SI 2 "register_operand" "r")))))]
2875   ""
2876   "<su>msubl\\t%0, %w1, %w2, %3"
2877   [(set_attr "type" "<su>mlal")]
2880 (define_insn "*<su_optab>mulsidi_neg"
2881   [(set (match_operand:DI 0 "register_operand" "=r")
2882         (mult:DI (neg:DI
2883                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2884                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2885   ""
2886   "<su>mnegl\\t%0, %w1, %w2"
2887   [(set_attr "type" "<su>mull")]
2890 (define_expand "<su_optab>mulditi3"
2891   [(set (match_operand:TI 0 "register_operand")
2892         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2893                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2894   ""
2896   rtx low = gen_reg_rtx (DImode);
2897   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2899   rtx high = gen_reg_rtx (DImode);
2900   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2902   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2903   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2904   DONE;
2907 ;; The default expansion of multi3 using umuldi3_highpart will perform
2908 ;; the additions in an order that fails to combine into two madd insns.
2909 (define_expand "multi3"
2910   [(set (match_operand:TI 0 "register_operand")
2911         (mult:TI (match_operand:TI 1 "register_operand")
2912                  (match_operand:TI 2 "register_operand")))]
2913   ""
2915   rtx l0 = gen_reg_rtx (DImode);
2916   rtx l1 = gen_lowpart (DImode, operands[1]);
2917   rtx l2 = gen_lowpart (DImode, operands[2]);
2918   rtx h0 = gen_reg_rtx (DImode);
2919   rtx h1 = gen_highpart (DImode, operands[1]);
2920   rtx h2 = gen_highpart (DImode, operands[2]);
2922   emit_insn (gen_muldi3 (l0, l1, l2));
2923   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2924   emit_insn (gen_madddi (h0, h1, l2, h0));
2925   emit_insn (gen_madddi (h0, l1, h2, h0));
2927   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2928   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2929   DONE;
2932 (define_insn "<su>muldi3_highpart"
2933   [(set (match_operand:DI 0 "register_operand" "=r")
2934         (truncate:DI
2935          (lshiftrt:TI
2936           (mult:TI
2937            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2938            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2939           (const_int 64))))]
2940   ""
2941   "<su>mulh\\t%0, %1, %2"
2942   [(set_attr "type" "<su>mull")]
2945 (define_insn "<su_optab>div<mode>3"
2946   [(set (match_operand:GPI 0 "register_operand" "=r")
2947         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2948                      (match_operand:GPI 2 "register_operand" "r")))]
2949   ""
2950   "<su>div\\t%<w>0, %<w>1, %<w>2"
2951   [(set_attr "type" "<su>div")]
2954 ;; zero_extend version of above
2955 (define_insn "*<su_optab>divsi3_uxtw"
2956   [(set (match_operand:DI 0 "register_operand" "=r")
2957         (zero_extend:DI
2958          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2959                      (match_operand:SI 2 "register_operand" "r"))))]
2960   ""
2961   "<su>div\\t%w0, %w1, %w2"
2962   [(set_attr "type" "<su>div")]
2965 ;; -------------------------------------------------------------------
2966 ;; Comparison insns
2967 ;; -------------------------------------------------------------------
2969 (define_insn "cmp<mode>"
2970   [(set (reg:CC CC_REGNUM)
2971         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2972                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2973   ""
2974   "@
2975    cmp\\t%<w>0, %<w>1
2976    cmp\\t%<w>0, %1
2977    cmn\\t%<w>0, #%n1"
2978   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2981 (define_insn "fcmp<mode>"
2982   [(set (reg:CCFP CC_REGNUM)
2983         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2984                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2985    "TARGET_FLOAT"
2986    "@
2987     fcmp\\t%<s>0, #0.0
2988     fcmp\\t%<s>0, %<s>1"
2989   [(set_attr "type" "fcmp<s>")]
2992 (define_insn "fcmpe<mode>"
2993   [(set (reg:CCFPE CC_REGNUM)
2994         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2995                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2996    "TARGET_FLOAT"
2997    "@
2998     fcmpe\\t%<s>0, #0.0
2999     fcmpe\\t%<s>0, %<s>1"
3000   [(set_attr "type" "fcmp<s>")]
3003 (define_insn "*cmp_swp_<shift>_reg<mode>"
3004   [(set (reg:CC_SWP CC_REGNUM)
3005         (compare:CC_SWP (ASHIFT:GPI
3006                          (match_operand:GPI 0 "register_operand" "r")
3007                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3008                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3009   ""
3010   "cmp\\t%<w>2, %<w>0, <shift> %1"
3011   [(set_attr "type" "alus_shift_imm")]
3014 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3015   [(set (reg:CC_SWP CC_REGNUM)
3016         (compare:CC_SWP (ANY_EXTEND:GPI
3017                          (match_operand:ALLX 0 "register_operand" "r"))
3018                         (match_operand:GPI 1 "register_operand" "r")))]
3019   ""
3020   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3021   [(set_attr "type" "alus_ext")]
3024 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3025   [(set (reg:CC_SWP CC_REGNUM)
3026         (compare:CC_SWP (ashift:GPI
3027                          (ANY_EXTEND:GPI
3028                           (match_operand:ALLX 0 "register_operand" "r"))
3029                          (match_operand 1 "aarch64_imm3" "Ui3"))
3030         (match_operand:GPI 2 "register_operand" "r")))]
3031   ""
3032   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3033   [(set_attr "type" "alus_ext")]
3036 ;; -------------------------------------------------------------------
3037 ;; Store-flag and conditional select insns
3038 ;; -------------------------------------------------------------------
3040 (define_expand "cstore<mode>4"
3041   [(set (match_operand:SI 0 "register_operand" "")
3042         (match_operator:SI 1 "aarch64_comparison_operator"
3043          [(match_operand:GPI 2 "register_operand" "")
3044           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3045   ""
3046   "
3047   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3048                                       operands[3]);
3049   operands[3] = const0_rtx;
3050   "
3053 (define_expand "cstorecc4"
3054   [(set (match_operand:SI 0 "register_operand")
3055        (match_operator 1 "aarch64_comparison_operator_mode"
3056         [(match_operand 2 "cc_register")
3057          (match_operand 3 "const0_operand")]))]
3058   ""
3060   emit_insn (gen_rtx_SET (operands[0], operands[1]));
3061   DONE;
3065 (define_expand "cstore<mode>4"
3066   [(set (match_operand:SI 0 "register_operand" "")
3067         (match_operator:SI 1 "aarch64_comparison_operator_mode"
3068          [(match_operand:GPF 2 "register_operand" "")
3069           (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3070   ""
3071   "
3072   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3073                                       operands[3]);
3074   operands[3] = const0_rtx;
3075   "
3078 (define_insn "aarch64_cstore<mode>"
3079   [(set (match_operand:ALLI 0 "register_operand" "=r")
3080         (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3081          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3082   ""
3083   "cset\\t%<w>0, %m1"
3084   [(set_attr "type" "csel")]
3087 ;; For a 24-bit immediate CST we can optimize the compare for equality
3088 ;; and branch sequence from:
3089 ;;      mov     x0, #imm1
3090 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
3091 ;;      cmp     x1, x0
3092 ;;      cset    x2, <ne,eq>
3093 ;; into the shorter:
3094 ;;      sub     x0, x1, #(CST & 0xfff000)
3095 ;;      subs    x0, x0, #(CST & 0x000fff)
3096 ;;      cset x2, <ne, eq>.
3097 (define_insn_and_split "*compare_cstore<mode>_insn"
3098   [(set (match_operand:GPI 0 "register_operand" "=r")
3099          (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3100                   (match_operand:GPI 2 "aarch64_imm24" "n")))]
3101   "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3102    && !aarch64_plus_operand (operands[2], <MODE>mode)
3103    && !reload_completed"
3104   "#"
3105   "&& true"
3106   [(const_int 0)]
3107   {
3108     HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3109     HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3110     rtx tmp = gen_reg_rtx (<MODE>mode);
3111     emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3112     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3113     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3114     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3115     emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3116     DONE;
3117   }
3118   [(set_attr "type" "csel")]
3121 ;; zero_extend version of the above
3122 (define_insn "*cstoresi_insn_uxtw"
3123   [(set (match_operand:DI 0 "register_operand" "=r")
3124         (zero_extend:DI
3125          (match_operator:SI 1 "aarch64_comparison_operator_mode"
3126           [(match_operand 2 "cc_register" "") (const_int 0)])))]
3127   ""
3128   "cset\\t%w0, %m1"
3129   [(set_attr "type" "csel")]
3132 (define_insn "cstore<mode>_neg"
3133   [(set (match_operand:ALLI 0 "register_operand" "=r")
3134         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3135                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
3136   ""
3137   "csetm\\t%<w>0, %m1"
3138   [(set_attr "type" "csel")]
3141 ;; zero_extend version of the above
3142 (define_insn "*cstoresi_neg_uxtw"
3143   [(set (match_operand:DI 0 "register_operand" "=r")
3144         (zero_extend:DI
3145          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3146                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3147   ""
3148   "csetm\\t%w0, %m1"
3149   [(set_attr "type" "csel")]
3152 (define_expand "cmov<mode>6"
3153   [(set (match_operand:GPI 0 "register_operand" "")
3154         (if_then_else:GPI
3155          (match_operator 1 "aarch64_comparison_operator"
3156           [(match_operand:GPI 2 "register_operand" "")
3157            (match_operand:GPI 3 "aarch64_plus_operand" "")])
3158          (match_operand:GPI 4 "register_operand" "")
3159          (match_operand:GPI 5 "register_operand" "")))]
3160   ""
3161   "
3162   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3163                                       operands[3]);
3164   operands[3] = const0_rtx;
3165   "
3168 (define_expand "cmov<mode>6"
3169   [(set (match_operand:GPF 0 "register_operand" "")
3170         (if_then_else:GPF
3171          (match_operator 1 "aarch64_comparison_operator"
3172           [(match_operand:GPF 2 "register_operand" "")
3173            (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3174          (match_operand:GPF 4 "register_operand" "")
3175          (match_operand:GPF 5 "register_operand" "")))]
3176   ""
3177   "
3178   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3179                                       operands[3]);
3180   operands[3] = const0_rtx;
3181   "
3184 (define_insn "*cmov<mode>_insn"
3185   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3186         (if_then_else:ALLI
3187          (match_operator 1 "aarch64_comparison_operator"
3188           [(match_operand 2 "cc_register" "") (const_int 0)])
3189          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3190          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3191   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3192      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3193   ;; Final two alternatives should be unreachable, but included for completeness
3194   "@
3195    csel\\t%<w>0, %<w>3, %<w>4, %m1
3196    csinv\\t%<w>0, %<w>3, <w>zr, %m1
3197    csinv\\t%<w>0, %<w>4, <w>zr, %M1
3198    csinc\\t%<w>0, %<w>3, <w>zr, %m1
3199    csinc\\t%<w>0, %<w>4, <w>zr, %M1
3200    mov\\t%<w>0, -1
3201    mov\\t%<w>0, 1"
3202   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3205 ;; zero_extend version of above
3206 (define_insn "*cmovsi_insn_uxtw"
3207   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3208         (zero_extend:DI
3209          (if_then_else:SI
3210           (match_operator 1 "aarch64_comparison_operator"
3211            [(match_operand 2 "cc_register" "") (const_int 0)])
3212           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3213           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3214   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3215      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3216   ;; Final two alternatives should be unreachable, but included for completeness
3217   "@
3218    csel\\t%w0, %w3, %w4, %m1
3219    csinv\\t%w0, %w3, wzr, %m1
3220    csinv\\t%w0, %w4, wzr, %M1
3221    csinc\\t%w0, %w3, wzr, %m1
3222    csinc\\t%w0, %w4, wzr, %M1
3223    mov\\t%w0, -1
3224    mov\\t%w0, 1"
3225   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3228 (define_insn "*cmovdi_insn_uxtw"
3229   [(set (match_operand:DI 0 "register_operand" "=r")
3230         (if_then_else:DI
3231          (match_operator 1 "aarch64_comparison_operator"
3232           [(match_operand 2 "cc_register" "") (const_int 0)])
3233          (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3234          (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3235   ""
3236   "csel\\t%w0, %w3, %w4, %m1"
3237   [(set_attr "type" "csel")]
3240 (define_insn "*cmov<mode>_insn"
3241   [(set (match_operand:GPF 0 "register_operand" "=w")
3242         (if_then_else:GPF
3243          (match_operator 1 "aarch64_comparison_operator"
3244           [(match_operand 2 "cc_register" "") (const_int 0)])
3245          (match_operand:GPF 3 "register_operand" "w")
3246          (match_operand:GPF 4 "register_operand" "w")))]
3247   "TARGET_FLOAT"
3248   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3249   [(set_attr "type" "fcsel")]
3252 (define_expand "mov<mode>cc"
3253   [(set (match_operand:ALLI 0 "register_operand" "")
3254         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3255                            (match_operand:ALLI 2 "register_operand" "")
3256                            (match_operand:ALLI 3 "register_operand" "")))]
3257   ""
3258   {
3259     rtx ccreg;
3260     enum rtx_code code = GET_CODE (operands[1]);
3262     if (code == UNEQ || code == LTGT)
3263       FAIL;
3265     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3266                                      XEXP (operands[1], 1));
3267     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3268   }
3271 (define_expand "mov<GPF:mode><GPI:mode>cc"
3272   [(set (match_operand:GPI 0 "register_operand" "")
3273         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3274                           (match_operand:GPF 2 "register_operand" "")
3275                           (match_operand:GPF 3 "register_operand" "")))]
3276   ""
3277   {
3278     rtx ccreg;
3279     enum rtx_code code = GET_CODE (operands[1]);
3281     if (code == UNEQ || code == LTGT)
3282       FAIL;
3284     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3285                                   XEXP (operands[1], 1));
3286     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3287   }
3290 (define_expand "mov<mode>cc"
3291   [(set (match_operand:GPF 0 "register_operand" "")
3292         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3293                           (match_operand:GPF 2 "register_operand" "")
3294                           (match_operand:GPF 3 "register_operand" "")))]
3295   ""
3296   {
3297     rtx ccreg;
3298     enum rtx_code code = GET_CODE (operands[1]);
3300     if (code == UNEQ || code == LTGT)
3301       FAIL;
3303     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3304                                   XEXP (operands[1], 1));
3305     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3306   }
3309 (define_expand "<neg_not_op><mode>cc"
3310   [(set (match_operand:GPI 0 "register_operand" "")
3311         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3312                           (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3313                           (match_operand:GPI 3 "register_operand" "")))]
3314   ""
3315   {
3316     rtx ccreg;
3317     enum rtx_code code = GET_CODE (operands[1]);
3319     if (code == UNEQ || code == LTGT)
3320       FAIL;
3322     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3323                                       XEXP (operands[1], 1));
3324     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3325   }
3328 ;; CRC32 instructions.
3329 (define_insn "aarch64_<crc_variant>"
3330   [(set (match_operand:SI 0 "register_operand" "=r")
3331         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3332                     (match_operand:<crc_mode> 2 "register_operand" "r")]
3333          CRC))]
3334   "TARGET_CRC32"
3335   {
3336     if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3337       return "<crc_variant>\\t%w0, %w1, %x2";
3338     else
3339       return "<crc_variant>\\t%w0, %w1, %w2";
3340   }
3341   [(set_attr "type" "crc")]
3344 (define_insn "*csinc2<mode>_insn"
3345   [(set (match_operand:GPI 0 "register_operand" "=r")
3346         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3347                   (match_operand:GPI 1 "register_operand" "r")))]
3348   ""
3349   "cinc\\t%<w>0, %<w>1, %m2"
3350   [(set_attr "type" "csel")]
3353 (define_insn "csinc3<mode>_insn"
3354   [(set (match_operand:GPI 0 "register_operand" "=r")
3355         (if_then_else:GPI
3356           (match_operand 1 "aarch64_comparison_operation" "")
3357           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3358                     (const_int 1))
3359           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3360   ""
3361   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3362   [(set_attr "type" "csel")]
3365 (define_insn "*csinv3<mode>_insn"
3366   [(set (match_operand:GPI 0 "register_operand" "=r")
3367         (if_then_else:GPI
3368           (match_operand 1 "aarch64_comparison_operation" "")
3369           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3370           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3371   ""
3372   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3373   [(set_attr "type" "csel")]
3376 (define_insn "csneg3_uxtw_insn"
3377   [(set (match_operand:DI 0 "register_operand" "=r")
3378         (zero_extend:DI
3379           (if_then_else:SI
3380             (match_operand 1 "aarch64_comparison_operation" "")
3381             (neg:SI (match_operand:SI 2 "register_operand" "r"))
3382             (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3383   ""
3384   "csneg\\t%w0, %w3, %w2, %M1"
3385   [(set_attr "type" "csel")]
3388 (define_insn "csneg3<mode>_insn"
3389   [(set (match_operand:GPI 0 "register_operand" "=r")
3390         (if_then_else:GPI
3391           (match_operand 1 "aarch64_comparison_operation" "")
3392           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3393           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3394   ""
3395   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3396   [(set_attr "type" "csel")]
3399 ;; -------------------------------------------------------------------
3400 ;; Logical operations
3401 ;; -------------------------------------------------------------------
3404 (define_insn_and_split "*aarch64_and<mode>_imm2"
3405   [(set (match_operand:GPI 0 "register_operand" "=rk")
3406         (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3407                  (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3408   ""
3409   "#"
3410   "true"
3411   [(const_int 0)]
3412   {
3413      HOST_WIDE_INT val = INTVAL (operands[2]);
3414      rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3415      rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3417      emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3418      emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3419      DONE;
3420   }
3423 (define_insn "<optab><mode>3"
3424   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3425         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3426                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3427   ""
3428   "@
3429   <logical>\\t%<w>0, %<w>1, %<w>2
3430   <logical>\\t%<w>0, %<w>1, %2
3431   <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3432   [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3433    (set_attr "simd" "*,*,yes")]
3436 ;; zero_extend version of above
3437 (define_insn "*<optab>si3_uxtw"
3438   [(set (match_operand:DI 0 "register_operand" "=r,rk")
3439         (zero_extend:DI
3440          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3441                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3442   ""
3443   "@
3444    <logical>\\t%w0, %w1, %w2
3445    <logical>\\t%w0, %w1, %2"
3446   [(set_attr "type" "logic_reg,logic_imm")]
3449 (define_insn "*and<mode>3_compare0"
3450   [(set (reg:CC_NZ CC_REGNUM)
3451         (compare:CC_NZ
3452          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3453                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3454          (const_int 0)))
3455    (set (match_operand:GPI 0 "register_operand" "=r,r")
3456         (and:GPI (match_dup 1) (match_dup 2)))]
3457   ""
3458   "@
3459    ands\\t%<w>0, %<w>1, %<w>2
3460    ands\\t%<w>0, %<w>1, %2"
3461   [(set_attr "type" "logics_reg,logics_imm")]
3464 ;; zero_extend version of above
3465 (define_insn "*andsi3_compare0_uxtw"
3466   [(set (reg:CC_NZ CC_REGNUM)
3467         (compare:CC_NZ
3468          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3469                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3470          (const_int 0)))
3471    (set (match_operand:DI 0 "register_operand" "=r,r")
3472         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3473   ""
3474   "@
3475    ands\\t%w0, %w1, %w2
3476    ands\\t%w0, %w1, %2"
3477   [(set_attr "type" "logics_reg,logics_imm")]
3480 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3481   [(set (reg:CC_NZ CC_REGNUM)
3482         (compare:CC_NZ
3483          (and:GPI (SHIFT:GPI
3484                    (match_operand:GPI 1 "register_operand" "r")
3485                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3486                   (match_operand:GPI 3 "register_operand" "r"))
3487          (const_int 0)))
3488    (set (match_operand:GPI 0 "register_operand" "=r")
3489         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3490   ""
3491   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3492   [(set_attr "type" "logics_shift_imm")]
3495 ;; zero_extend version of above
3496 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3497   [(set (reg:CC_NZ CC_REGNUM)
3498         (compare:CC_NZ
3499          (and:SI (SHIFT:SI
3500                   (match_operand:SI 1 "register_operand" "r")
3501                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3502                  (match_operand:SI 3 "register_operand" "r"))
3503          (const_int 0)))
3504    (set (match_operand:DI 0 "register_operand" "=r")
3505         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3506                                 (match_dup 3))))]
3507   ""
3508   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3509   [(set_attr "type" "logics_shift_imm")]
3512 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3513   [(set (match_operand:GPI 0 "register_operand" "=r")
3514         (LOGICAL:GPI (SHIFT: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:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3520   [(set_attr "type" "logic_shift_imm")]
3523 (define_insn "*<optab>_rol<mode>3"
3524   [(set (match_operand:GPI 0 "register_operand" "=r")
3525         (LOGICAL:GPI (rotate:GPI
3526                       (match_operand:GPI 1 "register_operand" "r")
3527                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3528                      (match_operand:GPI 3 "register_operand" "r")))]
3529   ""
3530   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3531   [(set_attr "type" "logic_shift_imm")]
3534 ;; zero_extend versions of above
3535 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3536   [(set (match_operand:DI 0 "register_operand" "=r")
3537         (zero_extend:DI
3538          (LOGICAL:SI (SHIFT:SI
3539                       (match_operand:SI 1 "register_operand" "r")
3540                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3541                      (match_operand:SI 3 "register_operand" "r"))))]
3542   ""
3543   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3544   [(set_attr "type" "logic_shift_imm")]
3547 (define_insn "*<optab>_rolsi3_uxtw"
3548   [(set (match_operand:DI 0 "register_operand" "=r")
3549         (zero_extend:DI
3550          (LOGICAL:SI (rotate:SI
3551                       (match_operand:SI 1 "register_operand" "r")
3552                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3553                      (match_operand:SI 3 "register_operand" "r"))))]
3554   ""
3555   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3556   [(set_attr "type" "logic_shift_imm")]
3559 (define_insn "one_cmpl<mode>2"
3560   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3561         (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3562   ""
3563   "@
3564   mvn\\t%<w>0, %<w>1
3565   mvn\\t%0.8b, %1.8b"
3566   [(set_attr "type" "logic_reg,neon_logic")
3567    (set_attr "simd" "*,yes")]
3570 (define_insn "*one_cmpl_<optab><mode>2"
3571   [(set (match_operand:GPI 0 "register_operand" "=r")
3572         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3573                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3574   ""
3575   "mvn\\t%<w>0, %<w>1, <shift> %2"
3576   [(set_attr "type" "logic_shift_imm")]
3579 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3581 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3582   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3583         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3584                      (match_operand:GPI 2 "register_operand" "r,w")))]
3585   ""
3586   "@
3587   <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3588   <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3589   [(set_attr "type" "logic_reg,neon_logic")
3590    (set_attr "simd" "*,yes")]
3593 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3594   [(set (match_operand:DI 0 "register_operand" "=r")
3595         (zero_extend:DI
3596           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3597                        (match_operand:SI 2 "register_operand" "r"))))]
3598   ""
3599   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3600   [(set_attr "type" "logic_reg")]
3603 (define_insn "*xor_one_cmplsidi3_ze"
3604   [(set (match_operand:DI 0 "register_operand" "=r")
3605         (zero_extend:DI
3606           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3607                           (match_operand:SI 2 "register_operand" "r")))))]
3608   ""
3609   "eon\\t%w0, %w1, %w2"
3610   [(set_attr "type" "logic_reg")]
3613 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3614 ;; eon does not operate on SIMD registers so the vector variant must be split.
3615 (define_insn_and_split "*xor_one_cmpl<mode>3"
3616   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3617         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3618                           (match_operand:GPI 2 "register_operand" "r,w"))))]
3619   ""
3620   "@
3621   eon\\t%<w>0, %<w>1, %<w>2
3622   #"
3623   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3624   [(set (match_operand:GPI 0 "register_operand" "=w")
3625         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3626                  (match_operand:GPI 2 "register_operand" "w")))
3627    (set (match_dup 0) (not:GPI (match_dup 0)))]
3628   ""
3629   [(set_attr "type" "logic_reg,multiple")
3630    (set_attr "simd" "*,yes")]
3633 (define_insn "*and_one_cmpl<mode>3_compare0"
3634   [(set (reg:CC_NZ CC_REGNUM)
3635         (compare:CC_NZ
3636          (and:GPI (not:GPI
3637                    (match_operand:GPI 1 "register_operand" "r"))
3638                   (match_operand:GPI 2 "register_operand" "r"))
3639          (const_int 0)))
3640    (set (match_operand:GPI 0 "register_operand" "=r")
3641         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3642   ""
3643   "bics\\t%<w>0, %<w>2, %<w>1"
3644   [(set_attr "type" "logics_reg")]
3647 ;; zero_extend version of above
3648 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3649   [(set (reg:CC_NZ CC_REGNUM)
3650         (compare:CC_NZ
3651          (and:SI (not:SI
3652                   (match_operand:SI 1 "register_operand" "r"))
3653                  (match_operand:SI 2 "register_operand" "r"))
3654          (const_int 0)))
3655    (set (match_operand:DI 0 "register_operand" "=r")
3656         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3657   ""
3658   "bics\\t%w0, %w2, %w1"
3659   [(set_attr "type" "logics_reg")]
3662 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3663   [(set (reg:CC_NZ CC_REGNUM)
3664     (compare:CC_NZ
3665      (and:GPI (not:GPI
3666            (match_operand:GPI 0 "register_operand" "r"))
3667           (match_operand:GPI 1 "register_operand" "r"))
3668      (const_int 0)))]
3669   ""
3670   "bics\\t<w>zr, %<w>1, %<w>0"
3671   [(set_attr "type" "logics_reg")]
3674 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3675   [(set (match_operand:GPI 0 "register_operand" "=r")
3676         (LOGICAL:GPI (not:GPI
3677                       (SHIFT:GPI
3678                        (match_operand:GPI 1 "register_operand" "r")
3679                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3680                      (match_operand:GPI 3 "register_operand" "r")))]
3681   ""
3682   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3683   [(set_attr "type" "logic_shift_imm")]
3686 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3687   [(set (match_operand:GPI 0 "register_operand" "=r")
3688         (not:GPI (xor:GPI
3689                       (SHIFT:GPI
3690                        (match_operand:GPI 1 "register_operand" "r")
3691                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3692                      (match_operand:GPI 3 "register_operand" "r"))))]
3693   ""
3694   "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3695   [(set_attr "type" "logic_shift_imm")]
3698 ;; Zero-extend version of the above.
3699 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3700   [(set (match_operand:DI 0 "register_operand" "=r")
3701         (zero_extend:DI
3702           (not:SI (xor:SI
3703                     (SHIFT:SI
3704                       (match_operand:SI 1 "register_operand" "r")
3705                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3706                     (match_operand:SI 3 "register_operand" "r")))))]
3707   ""
3708   "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3709   [(set_attr "type" "logic_shift_imm")]
3712 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3713   [(set (reg:CC_NZ CC_REGNUM)
3714         (compare:CC_NZ
3715          (and:GPI (not:GPI
3716                    (SHIFT:GPI
3717                     (match_operand:GPI 1 "register_operand" "r")
3718                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3719                   (match_operand:GPI 3 "register_operand" "r"))
3720          (const_int 0)))
3721    (set (match_operand:GPI 0 "register_operand" "=r")
3722         (and:GPI (not:GPI
3723                   (SHIFT:GPI
3724                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
3725   ""
3726   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3727   [(set_attr "type" "logics_shift_imm")]
3730 ;; zero_extend version of above
3731 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3732   [(set (reg:CC_NZ CC_REGNUM)
3733         (compare:CC_NZ
3734          (and:SI (not:SI
3735                   (SHIFT:SI
3736                    (match_operand:SI 1 "register_operand" "r")
3737                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3738                  (match_operand:SI 3 "register_operand" "r"))
3739          (const_int 0)))
3740    (set (match_operand:DI 0 "register_operand" "=r")
3741         (zero_extend:DI (and:SI
3742                          (not:SI
3743                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3744   ""
3745   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3746   [(set_attr "type" "logics_shift_imm")]
3749 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3750   [(set (reg:CC_NZ CC_REGNUM)
3751     (compare:CC_NZ
3752      (and:GPI (not:GPI
3753            (SHIFT:GPI
3754             (match_operand:GPI 0 "register_operand" "r")
3755             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3756           (match_operand:GPI 2 "register_operand" "r"))
3757      (const_int 0)))]
3758   ""
3759   "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3760   [(set_attr "type" "logics_shift_imm")]
3763 (define_insn "clz<mode>2"
3764   [(set (match_operand:GPI 0 "register_operand" "=r")
3765         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3766   ""
3767   "clz\\t%<w>0, %<w>1"
3768   [(set_attr "type" "clz")]
3771 (define_expand "ffs<mode>2"
3772   [(match_operand:GPI 0 "register_operand")
3773    (match_operand:GPI 1 "register_operand")]
3774   ""
3775   {
3776     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3777     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3779     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3780     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3781     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3782     DONE;
3783   }
3786 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
3788 ;; MOV  v.1d, x0
3789 ;; CNT  v1.8b, v.8b
3790 ;; ADDV b2, v1.8b
3791 ;; MOV  w0, v2.b[0]
3793 (define_expand "popcount<mode>2"
3794   [(match_operand:GPI 0 "register_operand")
3795    (match_operand:GPI 1 "register_operand")]
3796   "TARGET_SIMD"
3798   rtx v = gen_reg_rtx (V8QImode);
3799   rtx v1 = gen_reg_rtx (V8QImode);
3800   rtx r = gen_reg_rtx (QImode);
3801   rtx in = operands[1];
3802   rtx out = operands[0];
3803   if(<MODE>mode == SImode)
3804     {
3805       rtx tmp;
3806       tmp = gen_reg_rtx (DImode);
3807       /* If we have SImode, zero extend to DImode, pop count does
3808          not change if we have extra zeros. */
3809       emit_insn (gen_zero_extendsidi2 (tmp, in));
3810       in = tmp;
3811     }
3812   emit_move_insn (v, gen_lowpart (V8QImode, in));
3813   emit_insn (gen_popcountv8qi2 (v1, v));
3814   emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
3815   emit_insn (gen_zero_extendqi<mode>2 (out, r));
3816   DONE;
3819 (define_insn "clrsb<mode>2"
3820   [(set (match_operand:GPI 0 "register_operand" "=r")
3821         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3822   ""
3823   "cls\\t%<w>0, %<w>1"
3824   [(set_attr "type" "clz")]
3827 (define_insn "rbit<mode>2"
3828   [(set (match_operand:GPI 0 "register_operand" "=r")
3829         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3830   ""
3831   "rbit\\t%<w>0, %<w>1"
3832   [(set_attr "type" "rbit")]
3835 ;; Split after reload into RBIT + CLZ.  Since RBIT is represented as an UNSPEC
3836 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3837 ;; expression and split after reload to enable scheduling them apart if
3838 ;; needed.
3840 (define_insn_and_split "ctz<mode>2"
3841  [(set (match_operand:GPI           0 "register_operand" "=r")
3842        (ctz:GPI (match_operand:GPI  1 "register_operand" "r")))]
3843   ""
3844   "#"
3845   "reload_completed"
3846   [(const_int 0)]
3847   "
3848   emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3849   emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3850   DONE;
3853 (define_insn "*and<mode>_compare0"
3854   [(set (reg:CC_NZ CC_REGNUM)
3855         (compare:CC_NZ
3856          (match_operand:SHORT 0 "register_operand" "r")
3857          (const_int 0)))]
3858   ""
3859   "tst\\t%<w>0, <short_mask>"
3860   [(set_attr "type" "alus_imm")]
3863 (define_insn "*ands<mode>_compare0"
3864   [(set (reg:CC_NZ CC_REGNUM)
3865         (compare:CC_NZ
3866          (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3867          (const_int 0)))
3868    (set (match_operand:GPI 0 "register_operand" "=r")
3869         (zero_extend:GPI (match_dup 1)))]
3870   ""
3871   "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3872   [(set_attr "type" "alus_imm")]
3875 (define_insn "*and<mode>3nr_compare0"
3876   [(set (reg:CC_NZ CC_REGNUM)
3877         (compare:CC_NZ
3878          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3879                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3880          (const_int 0)))]
3881   ""
3882   "@
3883    tst\\t%<w>0, %<w>1
3884    tst\\t%<w>0, %1"
3885   [(set_attr "type" "logics_reg,logics_imm")]
3888 (define_insn "*and<mode>3nr_compare0_zextract"
3889   [(set (reg:CC_NZ CC_REGNUM)
3890         (compare:CC_NZ
3891          (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3892                   (match_operand:GPI 1 "const_int_operand" "n")
3893                   (match_operand:GPI 2 "const_int_operand" "n"))
3894          (const_int 0)))]
3895   "INTVAL (operands[1]) > 0
3896    && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3897         <= GET_MODE_BITSIZE (<MODE>mode))
3898    && aarch64_bitmask_imm (
3899         UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3900                                                  operands[2])),
3901         <MODE>mode)"
3902   {
3903     operands[1]
3904       = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3905     return "tst\\t%<w>0, %1";
3906   }
3907   [(set_attr "type" "logics_shift_imm")]
3910 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3911   [(set (reg:CC_NZ CC_REGNUM)
3912         (compare:CC_NZ
3913          (and:GPI (SHIFT:GPI
3914                    (match_operand:GPI 0 "register_operand" "r")
3915                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3916                   (match_operand:GPI 2 "register_operand" "r"))
3917         (const_int 0)))]
3918   ""
3919   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3920   [(set_attr "type" "logics_shift_imm")]
3923 ;; -------------------------------------------------------------------
3924 ;; Shifts
3925 ;; -------------------------------------------------------------------
3927 (define_expand "<optab><mode>3"
3928   [(set (match_operand:GPI 0 "register_operand")
3929         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3930                     (match_operand:QI 2 "nonmemory_operand")))]
3931   ""
3932   {
3933     if (CONST_INT_P (operands[2]))
3934       {
3935         operands[2] = GEN_INT (INTVAL (operands[2])
3936                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3938         if (operands[2] == const0_rtx)
3939           {
3940             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3941             DONE;
3942           }
3943       }
3944   }
3947 (define_expand "ashl<mode>3"
3948   [(set (match_operand:SHORT 0 "register_operand")
3949         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3950                       (match_operand:QI 2 "const_int_operand")))]
3951   ""
3952   {
3953     operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3955     if (operands[2] == const0_rtx)
3956       {
3957         emit_insn (gen_mov<mode> (operands[0], operands[1]));
3958         DONE;
3959       }
3960   }
3963 (define_expand "rotr<mode>3"
3964   [(set (match_operand:GPI 0 "register_operand")
3965         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3966                       (match_operand:QI 2 "nonmemory_operand")))]
3967   ""
3968   {
3969     if (CONST_INT_P (operands[2]))
3970       {
3971         operands[2] = GEN_INT (INTVAL (operands[2])
3972                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3974         if (operands[2] == const0_rtx)
3975           {
3976             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3977             DONE;
3978           }
3979       }
3980   }
3983 (define_expand "rotl<mode>3"
3984   [(set (match_operand:GPI 0 "register_operand")
3985         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3986                       (match_operand:QI 2 "nonmemory_operand")))]
3987   ""
3988   {
3989     /* (SZ - cnt) % SZ == -cnt % SZ */
3990     if (CONST_INT_P (operands[2]))
3991       {
3992         operands[2] = GEN_INT ((-INTVAL (operands[2]))
3993                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3994         if (operands[2] == const0_rtx)
3995           {
3996             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3997             DONE;
3998           }
3999       }
4000     else
4001       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
4002                                         NULL_RTX, 1);
4003   }
4006 ;; Logical left shift using SISD or Integer instruction
4007 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
4008   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
4009         (ashift:GPI
4010           (match_operand:GPI 1 "register_operand" "r,r,w,w")
4011           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
4012   ""
4013   "@
4014    lsl\t%<w>0, %<w>1, %2
4015    lsl\t%<w>0, %<w>1, %<w>2
4016    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4017    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
4018   [(set_attr "simd" "no,no,yes,yes")
4019    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
4022 ;; Logical right shift using SISD or Integer instruction
4023 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
4024   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4025         (lshiftrt:GPI
4026          (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4027          (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
4028   ""
4029   "@
4030    lsr\t%<w>0, %<w>1, %2
4031    lsr\t%<w>0, %<w>1, %<w>2
4032    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4033    #
4034    #"
4035   [(set_attr "simd" "no,no,yes,yes,yes")
4036    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4039 (define_split
4040   [(set (match_operand:DI 0 "aarch64_simd_register")
4041         (lshiftrt:DI
4042            (match_operand:DI 1 "aarch64_simd_register")
4043            (match_operand:QI 2 "aarch64_simd_register")))]
4044   "TARGET_SIMD && reload_completed"
4045   [(set (match_dup 3)
4046         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4047    (set (match_dup 0)
4048         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4049   {
4050     operands[3] = gen_lowpart (QImode, operands[0]);
4051   }
4054 (define_split
4055   [(set (match_operand:SI 0 "aarch64_simd_register")
4056         (lshiftrt:SI
4057            (match_operand:SI 1 "aarch64_simd_register")
4058            (match_operand:QI 2 "aarch64_simd_register")))]
4059   "TARGET_SIMD && reload_completed"
4060   [(set (match_dup 3)
4061         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4062    (set (match_dup 0)
4063         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4064   {
4065     operands[3] = gen_lowpart (QImode, operands[0]);
4066   }
4069 ;; Arithmetic right shift using SISD or Integer instruction
4070 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4071   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4072         (ashiftrt:GPI
4073           (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4074           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4075   ""
4076   "@
4077    asr\t%<w>0, %<w>1, %2
4078    asr\t%<w>0, %<w>1, %<w>2
4079    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4080    #
4081    #"
4082   [(set_attr "simd" "no,no,yes,yes,yes")
4083    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4086 (define_split
4087   [(set (match_operand:DI 0 "aarch64_simd_register")
4088         (ashiftrt:DI
4089            (match_operand:DI 1 "aarch64_simd_register")
4090            (match_operand:QI 2 "aarch64_simd_register")))]
4091   "TARGET_SIMD && reload_completed"
4092   [(set (match_dup 3)
4093         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4094    (set (match_dup 0)
4095         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4097   operands[3] = gen_lowpart (QImode, operands[0]);
4101 (define_split
4102   [(set (match_operand:SI 0 "aarch64_simd_register")
4103         (ashiftrt:SI
4104            (match_operand:SI 1 "aarch64_simd_register")
4105            (match_operand:QI 2 "aarch64_simd_register")))]
4106   "TARGET_SIMD && reload_completed"
4107   [(set (match_dup 3)
4108         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4109    (set (match_dup 0)
4110         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4112   operands[3] = gen_lowpart (QImode, operands[0]);
4116 (define_insn "*aarch64_sisd_ushl"
4117   [(set (match_operand:DI 0 "register_operand" "=w")
4118         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4119                     (match_operand:QI 2 "register_operand" "w")]
4120                    UNSPEC_SISD_USHL))]
4121   "TARGET_SIMD"
4122   "ushl\t%d0, %d1, %d2"
4123   [(set_attr "simd" "yes")
4124    (set_attr "type" "neon_shift_reg")]
4127 (define_insn "*aarch64_ushl_2s"
4128   [(set (match_operand:SI 0 "register_operand" "=w")
4129         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4130                     (match_operand:QI 2 "register_operand" "w")]
4131                    UNSPEC_USHL_2S))]
4132   "TARGET_SIMD"
4133   "ushl\t%0.2s, %1.2s, %2.2s"
4134   [(set_attr "simd" "yes")
4135    (set_attr "type" "neon_shift_reg")]
4138 (define_insn "*aarch64_sisd_sshl"
4139   [(set (match_operand:DI 0 "register_operand" "=w")
4140         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4141                     (match_operand:QI 2 "register_operand" "w")]
4142                    UNSPEC_SISD_SSHL))]
4143   "TARGET_SIMD"
4144   "sshl\t%d0, %d1, %d2"
4145   [(set_attr "simd" "yes")
4146    (set_attr "type" "neon_shift_reg")]
4149 (define_insn "*aarch64_sshl_2s"
4150   [(set (match_operand:SI 0 "register_operand" "=w")
4151         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4152                     (match_operand:QI 2 "register_operand" "w")]
4153                    UNSPEC_SSHL_2S))]
4154   "TARGET_SIMD"
4155   "sshl\t%0.2s, %1.2s, %2.2s"
4156   [(set_attr "simd" "yes")
4157    (set_attr "type" "neon_shift_reg")]
4160 (define_insn "*aarch64_sisd_neg_qi"
4161   [(set (match_operand:QI 0 "register_operand" "=w")
4162         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4163                    UNSPEC_SISD_NEG))]
4164   "TARGET_SIMD"
4165   "neg\t%d0, %d1"
4166   [(set_attr "simd" "yes")
4167    (set_attr "type" "neon_neg")]
4170 ;; Rotate right
4171 (define_insn "*ror<mode>3_insn"
4172   [(set (match_operand:GPI 0 "register_operand" "=r,r")
4173      (rotatert:GPI
4174        (match_operand:GPI 1 "register_operand" "r,r")
4175        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4176   ""
4177   "@
4178    ror\\t%<w>0, %<w>1, %2
4179    ror\\t%<w>0, %<w>1, %<w>2"
4180   [(set_attr "type" "rotate_imm,shift_reg")]
4183 ;; zero_extend version of above
4184 (define_insn "*<optab>si3_insn_uxtw"
4185   [(set (match_operand:DI 0 "register_operand" "=r,r")
4186         (zero_extend:DI (SHIFT:SI
4187          (match_operand:SI 1 "register_operand" "r,r")
4188          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4189   ""
4190   "@
4191    <shift>\\t%w0, %w1, %2
4192    <shift>\\t%w0, %w1, %w2"
4193   [(set_attr "type" "bfx,shift_reg")]
4196 (define_insn "*<optab><mode>3_insn"
4197   [(set (match_operand:SHORT 0 "register_operand" "=r")
4198         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4199                       (match_operand 2 "const_int_operand" "n")))]
4200   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4202   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4203   return "<bfshift>\t%w0, %w1, %2, %3";
4205   [(set_attr "type" "bfx")]
4208 (define_insn "*extr<mode>5_insn"
4209   [(set (match_operand:GPI 0 "register_operand" "=r")
4210         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4211                              (match_operand 3 "const_int_operand" "n"))
4212                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4213                                (match_operand 4 "const_int_operand" "n"))))]
4214   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4215    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4216   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4217   [(set_attr "type" "rotate_imm")]
4220 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4221 ;; so we have to match both orderings.
4222 (define_insn "*extr<mode>5_insn_alt"
4223   [(set (match_operand:GPI 0 "register_operand" "=r")
4224         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4225                                 (match_operand 4 "const_int_operand" "n"))
4226                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4227                               (match_operand 3 "const_int_operand" "n"))))]
4228   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4229    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4230        == GET_MODE_BITSIZE (<MODE>mode))"
4231   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4232   [(set_attr "type" "rotate_imm")]
4235 ;; zero_extend version of the above
4236 (define_insn "*extrsi5_insn_uxtw"
4237   [(set (match_operand:DI 0 "register_operand" "=r")
4238         (zero_extend:DI
4239          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4240                             (match_operand 3 "const_int_operand" "n"))
4241                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4242                               (match_operand 4 "const_int_operand" "n")))))]
4243   "UINTVAL (operands[3]) < 32 &&
4244    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4245   "extr\\t%w0, %w1, %w2, %4"
4246   [(set_attr "type" "rotate_imm")]
4249 (define_insn "*extrsi5_insn_uxtw_alt"
4250   [(set (match_operand:DI 0 "register_operand" "=r")
4251         (zero_extend:DI
4252          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4253                                (match_operand 4 "const_int_operand" "n"))
4254                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
4255                             (match_operand 3 "const_int_operand" "n")))))]
4256   "UINTVAL (operands[3]) < 32 &&
4257    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4258   "extr\\t%w0, %w1, %w2, %4"
4259   [(set_attr "type" "rotate_imm")]
4262 (define_insn "*ror<mode>3_insn"
4263   [(set (match_operand:GPI 0 "register_operand" "=r")
4264         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4265                     (match_operand 2 "const_int_operand" "n")))]
4266   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4268   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4269   return "ror\\t%<w>0, %<w>1, %3";
4271   [(set_attr "type" "rotate_imm")]
4274 ;; zero_extend version of the above
4275 (define_insn "*rorsi3_insn_uxtw"
4276   [(set (match_operand:DI 0 "register_operand" "=r")
4277         (zero_extend:DI
4278          (rotate:SI (match_operand:SI 1 "register_operand" "r")
4279                     (match_operand 2 "const_int_operand" "n"))))]
4280   "UINTVAL (operands[2]) < 32"
4282   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4283   return "ror\\t%w0, %w1, %3";
4285   [(set_attr "type" "rotate_imm")]
4288 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4289   [(set (match_operand:GPI 0 "register_operand" "=r")
4290         (ANY_EXTEND:GPI
4291          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4292                        (match_operand 2 "const_int_operand" "n"))))]
4293   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4295   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4296   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4298   [(set_attr "type" "bfx")]
4301 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4302   [(set (match_operand:GPI 0 "register_operand" "=r")
4303         (zero_extend:GPI
4304          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4305                          (match_operand 2 "const_int_operand" "n"))))]
4306   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4308   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4309   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4311   [(set_attr "type" "bfx")]
4314 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4315   [(set (match_operand:GPI 0 "register_operand" "=r")
4316         (sign_extend:GPI
4317          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4318                          (match_operand 2 "const_int_operand" "n"))))]
4319   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4321   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4322   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4324   [(set_attr "type" "bfx")]
4327 ;; -------------------------------------------------------------------
4328 ;; Bitfields
4329 ;; -------------------------------------------------------------------
4331 (define_expand "<optab>"
4332   [(set (match_operand:DI 0 "register_operand" "=r")
4333         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4334                         (match_operand 2
4335                           "aarch64_simd_shift_imm_offset_di")
4336                         (match_operand 3 "aarch64_simd_shift_imm_di")))]
4337   ""
4338   {
4339     if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4340                    1, GET_MODE_BITSIZE (DImode) - 1))
4341      FAIL;
4342   }
4346 (define_insn "*<optab><mode>"
4347   [(set (match_operand:GPI 0 "register_operand" "=r")
4348         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4349                          (match_operand 2
4350                            "aarch64_simd_shift_imm_offset_<mode>" "n")
4351                          (match_operand 3
4352                            "aarch64_simd_shift_imm_<mode>" "n")))]
4353   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4354              1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4355   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4356   [(set_attr "type" "bfx")]
4359 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4360 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4361 (define_split
4362   [(set (match_operand:DI 0 "register_operand")
4363         (zero_extract:DI (match_operand:DI 1 "register_operand")
4364                          (match_operand 2
4365                            "aarch64_simd_shift_imm_offset_di")
4366                          (match_operand 3
4367                            "aarch64_simd_shift_imm_di")))]
4368   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4369              GET_MODE_BITSIZE (DImode) - 1)
4370    && (INTVAL (operands[2]) + INTVAL (operands[3]))
4371        == GET_MODE_BITSIZE (SImode)"
4372   [(set (match_dup 0)
4373         (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4374   {
4375     operands[4] = gen_lowpart (SImode, operands[1]);
4376   }
4379 ;; Bitfield Insert (insv)
4380 (define_expand "insv<mode>"
4381   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4382                           (match_operand 1 "const_int_operand")
4383                           (match_operand 2 "const_int_operand"))
4384         (match_operand:GPI 3 "general_operand"))]
4385   ""
4387   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4388   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4389   rtx value = operands[3];
4391   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4392     FAIL;
4394   if (CONST_INT_P (value))
4395     {
4396       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4398       /* Prefer AND/OR for inserting all zeros or all ones.  */
4399       if ((UINTVAL (value) & mask) == 0
4400            || (UINTVAL (value) & mask) == mask)
4401         FAIL;
4403       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
4404       if (width == 16 && (pos % 16) == 0)
4405         DONE;
4406     }
4407   operands[3] = force_reg (<MODE>mode, value);
4410 (define_insn "*insv_reg<mode>"
4411   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4412                           (match_operand 1 "const_int_operand" "n")
4413                           (match_operand 2 "const_int_operand" "n"))
4414         (match_operand:GPI 3 "register_operand" "r"))]
4415   "!(UINTVAL (operands[1]) == 0
4416      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4417          > GET_MODE_BITSIZE (<MODE>mode)))"
4418   "bfi\\t%<w>0, %<w>3, %2, %1"
4419   [(set_attr "type" "bfm")]
4422 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4423   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4424                           (match_operand 1 "const_int_operand" "n")
4425                           (match_operand 2 "const_int_operand" "n"))
4426         (zero_extend:GPI (match_operand:ALLX 3  "register_operand" "r")))]
4427   "UINTVAL (operands[1]) <= <ALLX:sizen>"
4428   "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4429   [(set_attr "type" "bfm")]
4432 (define_insn "*extr_insv_lower_reg<mode>"
4433   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4434                           (match_operand 1 "const_int_operand" "n")
4435                           (const_int 0))
4436         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4437                           (match_dup 1)
4438                           (match_operand 3 "const_int_operand" "n")))]
4439   "!(UINTVAL (operands[1]) == 0
4440      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4441          > GET_MODE_BITSIZE (<MODE>mode)))"
4442   "bfxil\\t%<w>0, %<w>2, %3, %1"
4443   [(set_attr "type" "bfm")]
4446 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4447   [(set (match_operand:GPI 0 "register_operand" "=r")
4448         (ashift:GPI (ANY_EXTEND:GPI
4449                      (match_operand:ALLX 1 "register_operand" "r"))
4450                     (match_operand 2 "const_int_operand" "n")))]
4451   "UINTVAL (operands[2]) < <GPI:sizen>"
4453   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4454               ? GEN_INT (<ALLX:sizen>)
4455               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4456   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4458   [(set_attr "type" "bfx")]
4461 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4463 (define_insn "*andim_ashift<mode>_bfiz"
4464   [(set (match_operand:GPI 0 "register_operand" "=r")
4465         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4466                              (match_operand 2 "const_int_operand" "n"))
4467                  (match_operand 3 "const_int_operand" "n")))]
4468   "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4469   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4470   [(set_attr "type" "bfx")]
4473 ;; When the bit position and width of the equivalent extraction add up to 32
4474 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4475 ;; zero-extension of the X-reg.
4476 (define_split
4477   [(set (match_operand:DI 0 "register_operand")
4478         (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4479                              (match_operand 2 "const_int_operand"))
4480                  (match_operand 3 "const_int_operand")))]
4481  "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4482   && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4483       == GET_MODE_BITSIZE (SImode)"
4484   [(set (match_dup 0)
4485         (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4486   {
4487     operands[4] = gen_lowpart (SImode, operands[1]);
4488   }
4491 (define_insn "bswap<mode>2"
4492   [(set (match_operand:GPI 0 "register_operand" "=r")
4493         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4494   ""
4495   "rev\\t%<w>0, %<w>1"
4496   [(set_attr "type" "rev")]
4499 (define_insn "bswaphi2"
4500   [(set (match_operand:HI 0 "register_operand" "=r")
4501         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4502   ""
4503   "rev16\\t%w0, %w1"
4504   [(set_attr "type" "rev")]
4507 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4508 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4509 ;; each valid permutation.
4511 (define_insn "rev16<mode>2"
4512   [(set (match_operand:GPI 0 "register_operand" "=r")
4513         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4514                                       (const_int 8))
4515                           (match_operand:GPI 3 "const_int_operand" "n"))
4516                  (and:GPI (lshiftrt:GPI (match_dup 1)
4517                                         (const_int 8))
4518                           (match_operand:GPI 2 "const_int_operand" "n"))))]
4519   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4520    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4521   "rev16\\t%<w>0, %<w>1"
4522   [(set_attr "type" "rev")]
4525 (define_insn "rev16<mode>2_alt"
4526   [(set (match_operand:GPI 0 "register_operand" "=r")
4527         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4528                                         (const_int 8))
4529                           (match_operand:GPI 2 "const_int_operand" "n"))
4530                  (and:GPI (ashift:GPI (match_dup 1)
4531                                       (const_int 8))
4532                           (match_operand:GPI 3 "const_int_operand" "n"))))]
4533   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4534    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4535   "rev16\\t%<w>0, %<w>1"
4536   [(set_attr "type" "rev")]
4539 ;; zero_extend version of above
4540 (define_insn "*bswapsi2_uxtw"
4541   [(set (match_operand:DI 0 "register_operand" "=r")
4542         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4543   ""
4544   "rev\\t%w0, %w1"
4545   [(set_attr "type" "rev")]
4548 ;; -------------------------------------------------------------------
4549 ;; Floating-point intrinsics
4550 ;; -------------------------------------------------------------------
4552 ;; frint floating-point round to integral standard patterns.
4553 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4555 (define_insn "<frint_pattern><mode>2"
4556   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4557         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4558          FRINT))]
4559   "TARGET_FLOAT"
4560   "frint<frint_suffix>\\t%<s>0, %<s>1"
4561   [(set_attr "type" "f_rint<stype>")]
4564 ;; frcvt floating-point round to integer and convert standard patterns.
4565 ;; Expands to lbtrunc, lceil, lfloor, lround.
4566 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4567   [(set (match_operand:GPI 0 "register_operand" "=r")
4568         (FIXUORS:GPI
4569           (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4570            FCVT)))]
4571   "TARGET_FLOAT"
4572   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4573   [(set_attr "type" "f_cvtf2i")]
4576 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4577   [(set (match_operand:GPI 0 "register_operand" "=r")
4578         (FIXUORS:GPI
4579           (mult:GPF
4580             (match_operand:GPF 1 "register_operand" "w")
4581             (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4582   "TARGET_FLOAT
4583    && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4584                 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4585   {
4586     int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4587     char buf[64];
4588     snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4589     output_asm_insn (buf, operands);
4590     return "";
4591   }
4592   [(set_attr "type" "f_cvtf2i")]
4595 ;; fma - no throw
4597 (define_insn "fma<mode>4"
4598   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4599         (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4600                      (match_operand:GPF_F16 2 "register_operand" "w")
4601                      (match_operand:GPF_F16 3 "register_operand" "w")))]
4602   "TARGET_FLOAT"
4603   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4604   [(set_attr "type" "fmac<stype>")]
4607 (define_insn "fnma<mode>4"
4608   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4609         (fma:GPF_F16
4610           (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4611           (match_operand:GPF_F16 2 "register_operand" "w")
4612           (match_operand:GPF_F16 3 "register_operand" "w")))]
4613   "TARGET_FLOAT"
4614   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4615   [(set_attr "type" "fmac<stype>")]
4618 (define_insn "fms<mode>4"
4619   [(set (match_operand:GPF 0 "register_operand" "=w")
4620         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4621                  (match_operand:GPF 2 "register_operand" "w")
4622                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4623   "TARGET_FLOAT"
4624   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4625   [(set_attr "type" "fmac<s>")]
4628 (define_insn "fnms<mode>4"
4629   [(set (match_operand:GPF 0 "register_operand" "=w")
4630         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4631                  (match_operand:GPF 2 "register_operand" "w")
4632                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4633   "TARGET_FLOAT"
4634   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4635   [(set_attr "type" "fmac<s>")]
4638 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4639 (define_insn "*fnmadd<mode>4"
4640   [(set (match_operand:GPF 0 "register_operand" "=w")
4641         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4642                           (match_operand:GPF 2 "register_operand" "w")
4643                           (match_operand:GPF 3 "register_operand" "w"))))]
4644   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4645   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4646   [(set_attr "type" "fmac<s>")]
4649 ;; -------------------------------------------------------------------
4650 ;; Floating-point conversions
4651 ;; -------------------------------------------------------------------
4653 (define_insn "extendsfdf2"
4654   [(set (match_operand:DF 0 "register_operand" "=w")
4655         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4656   "TARGET_FLOAT"
4657   "fcvt\\t%d0, %s1"
4658   [(set_attr "type" "f_cvt")]
4661 (define_insn "extendhfsf2"
4662   [(set (match_operand:SF 0 "register_operand" "=w")
4663         (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4664   "TARGET_FLOAT"
4665   "fcvt\\t%s0, %h1"
4666   [(set_attr "type" "f_cvt")]
4669 (define_insn "extendhfdf2"
4670   [(set (match_operand:DF 0 "register_operand" "=w")
4671         (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4672   "TARGET_FLOAT"
4673   "fcvt\\t%d0, %h1"
4674   [(set_attr "type" "f_cvt")]
4677 (define_insn "truncdfsf2"
4678   [(set (match_operand:SF 0 "register_operand" "=w")
4679         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4680   "TARGET_FLOAT"
4681   "fcvt\\t%s0, %d1"
4682   [(set_attr "type" "f_cvt")]
4685 (define_insn "truncsfhf2"
4686   [(set (match_operand:HF 0 "register_operand" "=w")
4687         (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4688   "TARGET_FLOAT"
4689   "fcvt\\t%h0, %s1"
4690   [(set_attr "type" "f_cvt")]
4693 (define_insn "truncdfhf2"
4694   [(set (match_operand:HF 0 "register_operand" "=w")
4695         (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4696   "TARGET_FLOAT"
4697   "fcvt\\t%h0, %d1"
4698   [(set_attr "type" "f_cvt")]
4701 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4702   [(set (match_operand:GPI 0 "register_operand" "=r")
4703         (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4704   "TARGET_FLOAT"
4705   "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4706   [(set_attr "type" "f_cvtf2i")]
4709 (define_insn "<optab><fcvt_target><GPF:mode>2"
4710   [(set (match_operand:GPF 0 "register_operand" "=w,w")
4711         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4712   "TARGET_FLOAT"
4713   "@
4714    <su_optab>cvtf\t%<GPF:s>0, %<s>1
4715    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4716   [(set_attr "simd" "yes,no")
4717    (set_attr "fp" "no,yes")
4718    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4721 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4722   [(set (match_operand:GPF 0 "register_operand" "=w")
4723         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4724   "TARGET_FLOAT"
4725   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4726   [(set_attr "type" "f_cvti2f")]
4729 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4730 ;; midend will arrange for an SImode conversion to HFmode to first go
4731 ;; through DFmode, then to HFmode.  But first it will try converting
4732 ;; to DImode then down, which would match our DImode pattern below and
4733 ;; give very poor code-generation.  So, we must provide our own emulation
4734 ;; of the mid-end logic.
4736 (define_insn "aarch64_fp16_<optab><mode>hf2"
4737   [(set (match_operand:HF 0 "register_operand" "=w")
4738         (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4739   "TARGET_FP_F16INST"
4740   "<su_optab>cvtf\t%h0, %<w>1"
4741   [(set_attr "type" "f_cvti2f")]
4744 (define_expand "<optab>sihf2"
4745   [(set (match_operand:HF 0 "register_operand")
4746         (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4747   "TARGET_FLOAT"
4749   if (TARGET_FP_F16INST)
4750     emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4751   else
4752     {
4753       rtx convert_target = gen_reg_rtx (DFmode);
4754       emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4755       emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4756     }
4757   DONE;
4761 ;; For DImode there is no wide enough floating-point mode that we
4762 ;; can convert through natively (TFmode would work, but requires a library
4763 ;; call).  However, we know that any value >= 65504 will be rounded
4764 ;; to infinity on conversion.  This is well within the range of SImode, so
4765 ;; we can:
4766 ;;   Saturate to SImode.
4767 ;;   Convert from that to DFmode
4768 ;;   Convert from that to HFmode (phew!).
4769 ;; Note that the saturation to SImode requires the SIMD extensions.  If
4770 ;; we ever need to provide this pattern where the SIMD extensions are not
4771 ;; available, we would need a different approach.
4773 (define_expand "<optab>dihf2"
4774   [(set (match_operand:HF 0 "register_operand")
4775         (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4776   "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4778   if (TARGET_FP_F16INST)
4779     emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4780   else
4781     {
4782       rtx sat_target = gen_reg_rtx (SImode);
4783       emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4784       emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4785     }
4787   DONE;
4791 ;; Convert between fixed-point and floating-point (scalar modes)
4793 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4794   [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4795         (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4796                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4797          FCVT_F2FIXED))]
4798   ""
4799   "@
4800    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4801    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4802   [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4803    (set_attr "fp" "yes, *")
4804    (set_attr "simd" "*, yes")]
4807 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4808   [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4809         (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4810                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4811          FCVT_FIXED2F))]
4812   ""
4813   "@
4814    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4815    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4816   [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4817    (set_attr "fp" "yes, *")
4818    (set_attr "simd" "*, yes")]
4821 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4822   [(set (match_operand:GPI 0 "register_operand" "=r")
4823         (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4824                      (match_operand:SI 2 "immediate_operand" "i")]
4825          FCVT_F2FIXED))]
4826   "TARGET_FP_F16INST"
4827    "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4828   [(set_attr "type" "f_cvtf2i")]
4831 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4832   [(set (match_operand:HF 0 "register_operand" "=w")
4833         (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4834                     (match_operand:SI 2 "immediate_operand" "i")]
4835          FCVT_FIXED2F))]
4836   "TARGET_FP_F16INST"
4837   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4838   [(set_attr "type" "f_cvti2f")]
4841 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4842   [(set (match_operand:HI 0 "register_operand" "=w")
4843         (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4844                     (match_operand:SI 2 "immediate_operand" "i")]
4845          FCVT_F2FIXED))]
4846   "TARGET_SIMD"
4847   "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4848   [(set_attr "type" "neon_fp_to_int_s")]
4851 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4852   [(set (match_operand:HF 0 "register_operand" "=w")
4853         (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4854                     (match_operand:SI 2 "immediate_operand" "i")]
4855          FCVT_FIXED2F))]
4856   "TARGET_SIMD"
4857   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4858   [(set_attr "type" "neon_int_to_fp_s")]
4861 ;; -------------------------------------------------------------------
4862 ;; Floating-point arithmetic
4863 ;; -------------------------------------------------------------------
4865 (define_insn "add<mode>3"
4866   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4867         (plus:GPF_F16
4868          (match_operand:GPF_F16 1 "register_operand" "w")
4869          (match_operand:GPF_F16 2 "register_operand" "w")))]
4870   "TARGET_FLOAT"
4871   "fadd\\t%<s>0, %<s>1, %<s>2"
4872   [(set_attr "type" "fadd<stype>")]
4875 (define_insn "sub<mode>3"
4876   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4877         (minus:GPF_F16
4878          (match_operand:GPF_F16 1 "register_operand" "w")
4879          (match_operand:GPF_F16 2 "register_operand" "w")))]
4880   "TARGET_FLOAT"
4881   "fsub\\t%<s>0, %<s>1, %<s>2"
4882   [(set_attr "type" "fadd<stype>")]
4885 (define_insn "mul<mode>3"
4886   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4887         (mult:GPF_F16
4888          (match_operand:GPF_F16 1 "register_operand" "w")
4889          (match_operand:GPF_F16 2 "register_operand" "w")))]
4890   "TARGET_FLOAT"
4891   "fmul\\t%<s>0, %<s>1, %<s>2"
4892   [(set_attr "type" "fmul<stype>")]
4895 (define_insn "*fnmul<mode>3"
4896   [(set (match_operand:GPF 0 "register_operand" "=w")
4897         (mult:GPF
4898                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4899                  (match_operand:GPF 2 "register_operand" "w")))]
4900   "TARGET_FLOAT && !flag_rounding_math"
4901   "fnmul\\t%<s>0, %<s>1, %<s>2"
4902   [(set_attr "type" "fmul<s>")]
4905 (define_insn "*fnmul<mode>3"
4906   [(set (match_operand:GPF 0 "register_operand" "=w")
4907         (neg:GPF (mult:GPF
4908                  (match_operand:GPF 1 "register_operand" "w")
4909                  (match_operand:GPF 2 "register_operand" "w"))))]
4910   "TARGET_FLOAT"
4911   "fnmul\\t%<s>0, %<s>1, %<s>2"
4912   [(set_attr "type" "fmul<s>")]
4915 (define_expand "div<mode>3"
4916  [(set (match_operand:GPF_F16 0 "register_operand")
4917        (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4918                     (match_operand:GPF_F16 2 "register_operand")))]
4919  "TARGET_SIMD"
4921   if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4922     DONE;
4924   operands[1] = force_reg (<MODE>mode, operands[1]);
4927 (define_insn "*div<mode>3"
4928   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4929         (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4930                      (match_operand:GPF_F16 2 "register_operand" "w")))]
4931   "TARGET_FLOAT"
4932   "fdiv\\t%<s>0, %<s>1, %<s>2"
4933   [(set_attr "type" "fdiv<stype>")]
4936 (define_insn "neg<mode>2"
4937   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4938         (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4939   "TARGET_FLOAT"
4940   "fneg\\t%<s>0, %<s>1"
4941   [(set_attr "type" "ffarith<stype>")]
4944 (define_expand "sqrt<mode>2"
4945   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4946         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4947   "TARGET_FLOAT"
4949   if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4950     DONE;
4953 (define_insn "*sqrt<mode>2"
4954   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4955         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4956   "TARGET_FLOAT"
4957   "fsqrt\\t%<s>0, %<s>1"
4958   [(set_attr "type" "fsqrt<stype>")]
4961 (define_insn "abs<mode>2"
4962   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4963         (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4964   "TARGET_FLOAT"
4965   "fabs\\t%<s>0, %<s>1"
4966   [(set_attr "type" "ffarith<stype>")]
4969 ;; Given that smax/smin do not specify the result when either input is NaN,
4970 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4971 ;; for smin.
4973 (define_insn "smax<mode>3"
4974   [(set (match_operand:GPF 0 "register_operand" "=w")
4975         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4976                   (match_operand:GPF 2 "register_operand" "w")))]
4977   "TARGET_FLOAT"
4978   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4979   [(set_attr "type" "f_minmax<s>")]
4982 (define_insn "smin<mode>3"
4983   [(set (match_operand:GPF 0 "register_operand" "=w")
4984         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4985                   (match_operand:GPF 2 "register_operand" "w")))]
4986   "TARGET_FLOAT"
4987   "fminnm\\t%<s>0, %<s>1, %<s>2"
4988   [(set_attr "type" "f_minmax<s>")]
4991 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4992 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4993 ;; which implement the IEEE fmax ()/fmin () functions.
4994 (define_insn "<maxmin_uns><mode>3"
4995   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4996         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4997                      (match_operand:GPF_F16 2 "register_operand" "w")]
4998                      FMAXMIN_UNS))]
4999   "TARGET_FLOAT"
5000   "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
5001   [(set_attr "type" "f_minmax<stype>")]
5004 ;; For copysign (x, y), we want to generate:
5006 ;;   LDR d2, #(1 << 63)
5007 ;;   BSL v2.8b, [y], [x]
5009 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
5010 ;; aarch64_simd_bsldf will select the best suited of these instructions
5011 ;; to generate based on register allocation, and knows how to partially
5012 ;; constant fold based on the values of X and Y, so expand through that.
5014 (define_expand "copysigndf3"
5015   [(match_operand:DF 0 "register_operand")
5016    (match_operand:DF 1 "register_operand")
5017    (match_operand:DF 2 "register_operand")]
5018   "TARGET_FLOAT && TARGET_SIMD"
5020   rtx mask = gen_reg_rtx (DImode);
5021   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
5022   emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
5023                                      operands[2], operands[1]));
5024   DONE;
5028 ;; As above, but we must first get to a 64-bit value if we wish to use
5029 ;; aarch64_simd_bslv2sf.
5031 (define_expand "copysignsf3"
5032   [(match_operand:SF 0 "register_operand")
5033    (match_operand:SF 1 "register_operand")
5034    (match_operand:SF 2 "register_operand")]
5035   "TARGET_FLOAT && TARGET_SIMD"
5037   rtx mask = gen_reg_rtx (DImode);
5039   /* Juggle modes to get us in to a vector mode for BSL.  */
5040   rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
5041   rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
5042   rtx tmp = gen_reg_rtx (V2SFmode);
5043   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
5044   emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
5045   emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
5046   DONE;
5050 ;; -------------------------------------------------------------------
5051 ;; Reload support
5052 ;; -------------------------------------------------------------------
5053 ;; Reload Scalar Floating point modes from constant pool.
5054 ;; The AArch64 port doesn't have __int128 constant move support.
5055 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5056  [(set (match_operand:GPF_TF 0 "register_operand" "=w")
5057        (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
5058   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5059  "TARGET_FLOAT"
5061    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5062    emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5063    DONE;
5067 ;; Reload Vector modes from constant pool.
5068 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5069  [(set (match_operand:VALL 0 "register_operand" "=w")
5070        (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5071   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5072  "TARGET_FLOAT"
5074    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5075    emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5076    DONE;
5080 (define_expand "aarch64_reload_mov<mode>"
5081   [(set (match_operand:TX 0 "register_operand" "=w")
5082         (match_operand:TX 1 "register_operand" "w"))
5083    (clobber (match_operand:DI 2 "register_operand" "=&r"))
5084   ]
5085   "TARGET_FLOAT"
5086   {
5087     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5088     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5089     gen_aarch64_movtilow_tilow (op0, op1);
5090     gen_aarch64_movdi_tihigh (operands[2], op1);
5091     gen_aarch64_movtihigh_di (op0, operands[2]);
5092     DONE;
5093   }
5096 ;; The following secondary reload helpers patterns are invoked
5097 ;; after or during reload as we don't want these patterns to start
5098 ;; kicking in during the combiner.
5100 (define_insn "aarch64_movdi_<mode>low"
5101   [(set (match_operand:DI 0 "register_operand" "=r")
5102         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5103                          (const_int 64) (const_int 0)))]
5104   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5105   "fmov\\t%x0, %d1"
5106   [(set_attr "type" "f_mrc")
5107    (set_attr "length" "4")
5108   ])
5110 (define_insn "aarch64_movdi_<mode>high"
5111   [(set (match_operand:DI 0 "register_operand" "=r")
5112         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5113                          (const_int 64) (const_int 64)))]
5114   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5115   "fmov\\t%x0, %1.d[1]"
5116   [(set_attr "type" "f_mrc")
5117    (set_attr "length" "4")
5118   ])
5120 (define_insn "aarch64_mov<mode>high_di"
5121   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5122                          (const_int 64) (const_int 64))
5123         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5124   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5125   "fmov\\t%0.d[1], %x1"
5126   [(set_attr "type" "f_mcr")
5127    (set_attr "length" "4")
5128   ])
5130 (define_insn "aarch64_mov<mode>low_di"
5131   [(set (match_operand:TX 0 "register_operand" "=w")
5132         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5133   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5134   "fmov\\t%d0, %x1"
5135   [(set_attr "type" "f_mcr")
5136    (set_attr "length" "4")
5137   ])
5139 (define_insn "aarch64_movtilow_tilow"
5140   [(set (match_operand:TI 0 "register_operand" "=w")
5141         (zero_extend:TI
5142           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5143   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5144   "fmov\\t%d0, %d1"
5145   [(set_attr "type" "fmov")
5146    (set_attr "length" "4")
5147   ])
5149 ;; There is a deliberate reason why the parameters of high and lo_sum's
5150 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
5151 ;; and lo_sum's to be used with the labels defining the jump tables in
5152 ;; rodata section.
5154 (define_expand "add_losym"
5155   [(set (match_operand 0 "register_operand" "=r")
5156         (lo_sum (match_operand 1 "register_operand" "r")
5157                 (match_operand 2 "aarch64_valid_symref" "S")))]
5158   ""
5160   machine_mode mode = GET_MODE (operands[0]);
5162   emit_insn ((mode == DImode
5163               ? gen_add_losym_di
5164               : gen_add_losym_si) (operands[0],
5165                                    operands[1],
5166                                    operands[2]));
5167   DONE;
5170 (define_insn "add_losym_<mode>"
5171   [(set (match_operand:P 0 "register_operand" "=r")
5172         (lo_sum:P (match_operand:P 1 "register_operand" "r")
5173                   (match_operand 2 "aarch64_valid_symref" "S")))]
5174   ""
5175   "add\\t%<w>0, %<w>1, :lo12:%a2"
5176   [(set_attr "type" "alu_imm")]
5179 (define_insn "ldr_got_small_<mode>"
5180   [(set (match_operand:PTR 0 "register_operand" "=r")
5181         (unspec:PTR [(mem:PTR (lo_sum:PTR
5182                               (match_operand:PTR 1 "register_operand" "r")
5183                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5184                     UNSPEC_GOTSMALLPIC))]
5185   ""
5186   "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5187   [(set_attr "type" "load1")]
5190 (define_insn "ldr_got_small_sidi"
5191   [(set (match_operand:DI 0 "register_operand" "=r")
5192         (zero_extend:DI
5193          (unspec:SI [(mem:SI (lo_sum:DI
5194                              (match_operand:DI 1 "register_operand" "r")
5195                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5196                     UNSPEC_GOTSMALLPIC)))]
5197   "TARGET_ILP32"
5198   "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5199   [(set_attr "type" "load1")]
5202 (define_insn "ldr_got_small_28k_<mode>"
5203   [(set (match_operand:PTR 0 "register_operand" "=r")
5204         (unspec:PTR [(mem:PTR (lo_sum:PTR
5205                               (match_operand:PTR 1 "register_operand" "r")
5206                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5207                     UNSPEC_GOTSMALLPIC28K))]
5208   ""
5209   "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5210   [(set_attr "type" "load1")]
5213 (define_insn "ldr_got_small_28k_sidi"
5214   [(set (match_operand:DI 0 "register_operand" "=r")
5215         (zero_extend:DI
5216          (unspec:SI [(mem:SI (lo_sum:DI
5217                              (match_operand:DI 1 "register_operand" "r")
5218                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5219                     UNSPEC_GOTSMALLPIC28K)))]
5220   "TARGET_ILP32"
5221   "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5222   [(set_attr "type" "load1")]
5225 (define_insn "ldr_got_tiny"
5226   [(set (match_operand:DI 0 "register_operand" "=r")
5227         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5228                    UNSPEC_GOTTINYPIC))]
5229   ""
5230   "ldr\\t%0, %L1"
5231   [(set_attr "type" "load1")]
5234 (define_insn "aarch64_load_tp_hard"
5235   [(set (match_operand:DI 0 "register_operand" "=r")
5236         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5237   ""
5238   "mrs\\t%0, tpidr_el0"
5239   [(set_attr "type" "mrs")]
5242 ;; The TLS ABI specifically requires that the compiler does not schedule
5243 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5244 ;; Therefore we treat the stubs as an atomic sequence.
5245 (define_expand "tlsgd_small_<mode>"
5246  [(parallel [(set (match_operand 0 "register_operand" "")
5247                   (call (mem:DI (match_dup 2)) (const_int 1)))
5248              (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5249              (clobber (reg:DI LR_REGNUM))])]
5250  ""
5252   operands[2] = aarch64_tls_get_addr ();
5255 (define_insn "*tlsgd_small_<mode>"
5256   [(set (match_operand 0 "register_operand" "")
5257         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5258    (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5259    (clobber (reg:DI LR_REGNUM))
5260   ]
5261   ""
5262   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5263   [(set_attr "type" "call")
5264    (set_attr "length" "16")])
5266 (define_insn "tlsie_small_<mode>"
5267   [(set (match_operand:PTR 0 "register_operand" "=r")
5268         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5269                    UNSPEC_GOTSMALLTLS))]
5270   ""
5271   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5272   [(set_attr "type" "load1")
5273    (set_attr "length" "8")]
5276 (define_insn "tlsie_small_sidi"
5277   [(set (match_operand:DI 0 "register_operand" "=r")
5278         (zero_extend:DI
5279           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5280                       UNSPEC_GOTSMALLTLS)))]
5281   ""
5282   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5283   [(set_attr "type" "load1")
5284    (set_attr "length" "8")]
5287 (define_insn "tlsie_tiny_<mode>"
5288   [(set (match_operand:PTR 0 "register_operand" "=&r")
5289         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5290                      (match_operand:PTR 2 "register_operand" "r")]
5291                    UNSPEC_GOTTINYTLS))]
5292   ""
5293   "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5294   [(set_attr "type" "multiple")
5295    (set_attr "length" "8")]
5298 (define_insn "tlsie_tiny_sidi"
5299   [(set (match_operand:DI 0 "register_operand" "=&r")
5300         (zero_extend:DI
5301           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5302                       (match_operand:DI 2 "register_operand" "r")
5303                       ]
5304                       UNSPEC_GOTTINYTLS)))]
5305   ""
5306   "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5307   [(set_attr "type" "multiple")
5308    (set_attr "length" "8")]
5311 (define_insn "tlsle12_<mode>"
5312   [(set (match_operand:P 0 "register_operand" "=r")
5313         (unspec:P [(match_operand:P 1 "register_operand" "r")
5314                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5315                    UNSPEC_TLSLE12))]
5316   ""
5317   "add\\t%<w>0, %<w>1, #%L2";
5318   [(set_attr "type" "alu_sreg")
5319    (set_attr "length" "4")]
5322 (define_insn "tlsle24_<mode>"
5323   [(set (match_operand:P 0 "register_operand" "=r")
5324         (unspec:P [(match_operand:P 1 "register_operand" "r")
5325                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5326                    UNSPEC_TLSLE24))]
5327   ""
5328   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5329   [(set_attr "type" "multiple")
5330    (set_attr "length" "8")]
5333 (define_insn "tlsle32_<mode>"
5334   [(set (match_operand:P 0 "register_operand" "=r")
5335         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5336                    UNSPEC_TLSLE32))]
5337   ""
5338   "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5339   [(set_attr "type" "multiple")
5340    (set_attr "length" "8")]
5343 (define_insn "tlsle48_<mode>"
5344   [(set (match_operand:P 0 "register_operand" "=r")
5345         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5346                    UNSPEC_TLSLE48))]
5347   ""
5348   "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5349   [(set_attr "type" "multiple")
5350    (set_attr "length" "12")]
5353 (define_insn "tlsdesc_small_<mode>"
5354   [(set (reg:PTR R0_REGNUM)
5355         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5356                    UNSPEC_TLSDESC))
5357    (clobber (reg:DI LR_REGNUM))
5358    (clobber (reg:CC CC_REGNUM))
5359    (clobber (match_scratch:DI 1 "=r"))]
5360   "TARGET_TLS_DESC"
5361   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5362   [(set_attr "type" "call")
5363    (set_attr "length" "16")])
5365 (define_insn "stack_tie"
5366   [(set (mem:BLK (scratch))
5367         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5368                      (match_operand:DI 1 "register_operand" "rk")]
5369                     UNSPEC_PRLG_STK))]
5370   ""
5371   ""
5372   [(set_attr "length" "0")]
5375 ;; Pointer authentication patterns are always provided.  In architecture
5376 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
5377 ;; This lets the user write portable software which authenticates pointers
5378 ;; when run on something which implements ARMv8.3-A, and which runs
5379 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
5380 ;; implemented.
5382 ;; Signing/Authenticating R30 using SP as the salt.
5384 (define_insn "<pauth_mnem_prefix>sp"
5385   [(set (reg:DI R30_REGNUM)
5386         (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
5387   ""
5388   "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
5391 ;; Signing/Authenticating X17 using X16 as the salt.
5393 (define_insn "<pauth_mnem_prefix>1716"
5394   [(set (reg:DI R17_REGNUM)
5395         (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
5396   ""
5397   "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
5400 ;; Stripping the signature in R30.
5402 (define_insn "xpaclri"
5403   [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
5404   ""
5405   "hint\t7 // xpaclri"
5408 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5409 ;; all of memory.  This blocks insns from being moved across this point.
5411 (define_insn "blockage"
5412   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5413   ""
5414   ""
5415   [(set_attr "length" "0")
5416    (set_attr "type" "block")]
5419 (define_insn "probe_stack_range"
5420   [(set (match_operand:DI 0 "register_operand" "=r")
5421         (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
5422                              (match_operand:DI 2 "register_operand" "r")]
5423                               UNSPECV_PROBE_STACK_RANGE))]
5424   ""
5426   return aarch64_output_probe_stack_range (operands[0], operands[2]);
5428   [(set_attr "length" "32")]
5431 ;; Named pattern for expanding thread pointer reference.
5432 (define_expand "get_thread_pointerdi"
5433   [(match_operand:DI 0 "register_operand" "=r")]
5434   ""
5436   rtx tmp = aarch64_load_tp (operands[0]);
5437   if (tmp != operands[0])
5438     emit_move_insn (operands[0], tmp);
5439   DONE;
5442 ;; Named patterns for stack smashing protection.
5443 (define_expand "stack_protect_set"
5444   [(match_operand 0 "memory_operand")
5445    (match_operand 1 "memory_operand")]
5446   ""
5448   machine_mode mode = GET_MODE (operands[0]);
5450   emit_insn ((mode == DImode
5451               ? gen_stack_protect_set_di
5452               : gen_stack_protect_set_si) (operands[0], operands[1]));
5453   DONE;
5456 (define_insn "stack_protect_set_<mode>"
5457   [(set (match_operand:PTR 0 "memory_operand" "=m")
5458         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5459          UNSPEC_SP_SET))
5460    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5461   ""
5462   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5463   [(set_attr "length" "12")
5464    (set_attr "type" "multiple")])
5466 (define_expand "stack_protect_test"
5467   [(match_operand 0 "memory_operand")
5468    (match_operand 1 "memory_operand")
5469    (match_operand 2)]
5470   ""
5472   rtx result;
5473   machine_mode mode = GET_MODE (operands[0]);
5475   result = gen_reg_rtx(mode);
5477   emit_insn ((mode == DImode
5478               ? gen_stack_protect_test_di
5479               : gen_stack_protect_test_si) (result,
5480                                             operands[0],
5481                                             operands[1]));
5483   if (mode == DImode)
5484     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5485                                     result, const0_rtx, operands[2]));
5486   else
5487     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5488                                     result, const0_rtx, operands[2]));
5489   DONE;
5492 (define_insn "stack_protect_test_<mode>"
5493   [(set (match_operand:PTR 0 "register_operand" "=r")
5494         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5495                      (match_operand:PTR 2 "memory_operand" "m")]
5496          UNSPEC_SP_TEST))
5497    (clobber (match_scratch:PTR 3 "=&r"))]
5498   ""
5499   "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5500   [(set_attr "length" "12")
5501    (set_attr "type" "multiple")])
5503 ;; Write Floating-point Control Register.
5504 (define_insn "set_fpcr"
5505   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5506   ""
5507   "msr\\tfpcr, %0"
5508   [(set_attr "type" "mrs")])
5510 ;; Read Floating-point Control Register.
5511 (define_insn "get_fpcr"
5512   [(set (match_operand:SI 0 "register_operand" "=r")
5513         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5514   ""
5515   "mrs\\t%0, fpcr"
5516   [(set_attr "type" "mrs")])
5518 ;; Write Floating-point Status Register.
5519 (define_insn "set_fpsr"
5520   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5521   ""
5522   "msr\\tfpsr, %0"
5523   [(set_attr "type" "mrs")])
5525 ;; Read Floating-point Status Register.
5526 (define_insn "get_fpsr"
5527   [(set (match_operand:SI 0 "register_operand" "=r")
5528         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5529   ""
5530   "mrs\\t%0, fpsr"
5531   [(set_attr "type" "mrs")])
5534 ;; Define the subtract-one-and-jump insns so loop.c
5535 ;; knows what to generate.
5536 (define_expand "doloop_end"
5537   [(use (match_operand 0 "" ""))      ; loop pseudo
5538    (use (match_operand 1 "" ""))]     ; label
5539   "optimize > 0 && flag_modulo_sched"
5541   rtx s0;
5542   rtx bcomp;
5543   rtx loc_ref;
5544   rtx cc_reg;
5545   rtx insn;
5546   rtx cmp;
5548   /* Currently SMS relies on the do-loop pattern to recognize loops
5549      where (1) the control part consists of all insns defining and/or
5550      using a certain 'count' register and (2) the loop count can be
5551      adjusted by modifying this register prior to the loop.
5552      ??? The possible introduction of a new block to initialize the
5553      new IV can potentially affect branch optimizations.  */
5555   if (GET_MODE (operands[0]) != DImode)
5556     FAIL;
5558   s0 = operands [0];
5559   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5561   cmp = XVECEXP (PATTERN (insn), 0, 0);
5562   cc_reg = SET_DEST (cmp);
5563   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5564   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5565   emit_jump_insn (gen_rtx_SET (pc_rtx,
5566                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5567                                                      loc_ref, pc_rtx)));
5568   DONE;
5571 ;; AdvSIMD Stuff
5572 (include "aarch64-simd.md")
5574 ;; Atomic Operations
5575 (include "atomics.md")
5577 ;; ldp/stp peephole patterns
5578 (include "aarch64-ldpstp.md")