[AArch64] PR target/69161: Don't use special predicate for CCmode comparisons in...
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blob68676c9bd55421da903d5d40d21eaeba80cb2c4f
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2016 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; Register numbers
22 (define_constants
23   [
24     (R0_REGNUM          0)
25     (R1_REGNUM          1)
26     (R2_REGNUM          2)
27     (R3_REGNUM          3)
28     (R4_REGNUM          4)
29     (R5_REGNUM          5)
30     (R6_REGNUM          6)
31     (R7_REGNUM          7)
32     (R8_REGNUM          8)
33     (R9_REGNUM          9)
34     (R10_REGNUM         10)
35     (R11_REGNUM         11)
36     (R12_REGNUM         12)
37     (R13_REGNUM         13)
38     (R14_REGNUM         14)
39     (R15_REGNUM         15)
40     (R16_REGNUM         16)
41     (IP0_REGNUM         16)
42     (R17_REGNUM         17)
43     (IP1_REGNUM         17)
44     (R18_REGNUM         18)
45     (R19_REGNUM         19)
46     (R20_REGNUM         20)
47     (R21_REGNUM         21)
48     (R22_REGNUM         22)
49     (R23_REGNUM         23)
50     (R24_REGNUM         24)
51     (R25_REGNUM         25)
52     (R26_REGNUM         26)
53     (R27_REGNUM         27)
54     (R28_REGNUM         28)
55     (R29_REGNUM         29)
56     (R30_REGNUM         30)
57     (LR_REGNUM          30)
58     (SP_REGNUM          31)
59     (V0_REGNUM          32)
60     (V15_REGNUM         47)
61     (V31_REGNUM         63)
62     (SFP_REGNUM         64)
63     (AP_REGNUM          65)
64     (CC_REGNUM          66)
65   ]
68 (define_c_enum "unspec" [
69     UNSPEC_CASESI
70     UNSPEC_CRC32B
71     UNSPEC_CRC32CB
72     UNSPEC_CRC32CH
73     UNSPEC_CRC32CW
74     UNSPEC_CRC32CX
75     UNSPEC_CRC32H
76     UNSPEC_CRC32W
77     UNSPEC_CRC32X
78     UNSPEC_URECPE
79     UNSPEC_FRECPE
80     UNSPEC_FRECPS
81     UNSPEC_FRECPX
82     UNSPEC_FRINTA
83     UNSPEC_FRINTI
84     UNSPEC_FRINTM
85     UNSPEC_FRINTN
86     UNSPEC_FRINTP
87     UNSPEC_FRINTX
88     UNSPEC_FRINTZ
89     UNSPEC_GOTSMALLPIC
90     UNSPEC_GOTSMALLPIC28K
91     UNSPEC_GOTSMALLTLS
92     UNSPEC_GOTTINYPIC
93     UNSPEC_GOTTINYTLS
94     UNSPEC_LD1
95     UNSPEC_LD2
96     UNSPEC_LD2_DUP
97     UNSPEC_LD3
98     UNSPEC_LD3_DUP
99     UNSPEC_LD4
100     UNSPEC_LD4_DUP
101     UNSPEC_LD2_LANE
102     UNSPEC_LD3_LANE
103     UNSPEC_LD4_LANE
104     UNSPEC_MB
105     UNSPEC_NOP
106     UNSPEC_PRLG_STK
107     UNSPEC_RBIT
108     UNSPEC_SISD_NEG
109     UNSPEC_SISD_SSHL
110     UNSPEC_SISD_USHL
111     UNSPEC_SSHL_2S
112     UNSPEC_ST1
113     UNSPEC_ST2
114     UNSPEC_ST3
115     UNSPEC_ST4
116     UNSPEC_ST2_LANE
117     UNSPEC_ST3_LANE
118     UNSPEC_ST4_LANE
119     UNSPEC_TLS
120     UNSPEC_TLSDESC
121     UNSPEC_TLSLE12
122     UNSPEC_TLSLE24
123     UNSPEC_TLSLE32
124     UNSPEC_TLSLE48
125     UNSPEC_USHL_2S
126     UNSPEC_VSTRUCTDUMMY
127     UNSPEC_SP_SET
128     UNSPEC_SP_TEST
129     UNSPEC_RSQRT
130     UNSPEC_RSQRTE
131     UNSPEC_RSQRTS
132     UNSPEC_NZCV
135 (define_c_enum "unspecv" [
136     UNSPECV_EH_RETURN           ; Represent EH_RETURN
137     UNSPECV_GET_FPCR            ; Represent fetch of FPCR content.
138     UNSPECV_SET_FPCR            ; Represent assign of FPCR content.
139     UNSPECV_GET_FPSR            ; Represent fetch of FPSR content.
140     UNSPECV_SET_FPSR            ; Represent assign of FPSR content.
141     UNSPECV_BLOCKAGE            ; Represent a blockage
142     UNSPECV_PROBE_STACK_RANGE   ; Represent stack range probing.
143   ]
146 ;; If further include files are added the defintion of MD_INCLUDES
147 ;; must be updated.
149 (include "constraints.md")
150 (include "predicates.md")
151 (include "iterators.md")
153 ;; -------------------------------------------------------------------
154 ;; Instruction types and attributes
155 ;; -------------------------------------------------------------------
157 ; The "type" attribute is included here from AArch32 backend to be able
158 ; to share pipeline descriptions.
159 (include "../arm/types.md")
161 ;; It is important to set the fp or simd attributes to yes when a pattern
162 ;; alternative uses the FP or SIMD register files, usually signified by use of
163 ;; the 'w' constraint.  This will ensure that the alternative will be
164 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
165 ;; architecture extensions.  If all the alternatives in a pattern use the
166 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
167 ;; or TARGET_SIMD.
169 ;; Attribute that specifies whether or not the instruction touches fp
170 ;; registers.  When this is set to yes for an alternative, that alternative
171 ;; will be disabled when !TARGET_FLOAT.
172 (define_attr "fp" "no,yes" (const_string "no"))
174 ;; Attribute that specifies whether or not the instruction touches simd
175 ;; registers.  When this is set to yes for an alternative, that alternative
176 ;; will be disabled when !TARGET_SIMD.
177 (define_attr "simd" "no,yes" (const_string "no"))
179 (define_attr "length" ""
180   (const_int 4))
182 ;; Attribute that controls whether an alternative is enabled or not.
183 ;; Currently it is only used to disable alternatives which touch fp or simd
184 ;; registers when -mgeneral-regs-only is specified.
185 (define_attr "enabled" "no,yes"
186   (cond [(ior
187         (and (eq_attr "fp" "yes")
188              (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
189         (and (eq_attr "simd" "yes")
190              (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
191              (const_string "no")
192         ] (const_string "yes")))
194 ;; Attribute that specifies whether we are dealing with a branch to a
195 ;; label that is far away, i.e. further away than the maximum/minimum
196 ;; representable in a signed 21-bits number.
197 ;; 0 :=: no
198 ;; 1 :=: yes
199 (define_attr "far_branch" "" (const_int 0))
201 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
202 ;; no predicated insns.
203 (define_attr "predicated" "yes,no" (const_string "no"))
205 ;; -------------------------------------------------------------------
206 ;; Pipeline descriptions and scheduling
207 ;; -------------------------------------------------------------------
209 ;; Processor types.
210 (include "aarch64-tune.md")
212 ;; Scheduling
213 (include "../arm/cortex-a53.md")
214 (include "../arm/cortex-a57.md")
215 (include "../arm/exynos-m1.md")
216 (include "thunderx.md")
217 (include "../arm/xgene1.md")
219 ;; -------------------------------------------------------------------
220 ;; Jumps and other miscellaneous insns
221 ;; -------------------------------------------------------------------
223 (define_insn "indirect_jump"
224   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
225   ""
226   "br\\t%0"
227   [(set_attr "type" "branch")]
230 (define_insn "jump"
231   [(set (pc) (label_ref (match_operand 0 "" "")))]
232   ""
233   "b\\t%l0"
234   [(set_attr "type" "branch")]
237 (define_expand "cbranch<mode>4"
238   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
239                             [(match_operand:GPI 1 "register_operand" "")
240                              (match_operand:GPI 2 "aarch64_plus_operand" "")])
241                            (label_ref (match_operand 3 "" ""))
242                            (pc)))]
243   ""
244   "
245   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
246                                          operands[2]);
247   operands[2] = const0_rtx;
248   "
251 (define_expand "cbranch<mode>4"
252   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
253                             [(match_operand:GPF 1 "register_operand" "")
254                              (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
255                            (label_ref (match_operand 3 "" ""))
256                            (pc)))]
257   ""
258   "
259   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
260                                          operands[2]);
261   operands[2] = const0_rtx;
262   "
265 (define_expand "cbranchcc4"
266   [(set (pc) (if_then_else
267               (match_operator 0 "aarch64_comparison_operator"
268                [(match_operand 1 "cc_register" "")
269                 (match_operand 2 "const0_operand")])
270               (label_ref (match_operand 3 "" ""))
271               (pc)))]
272   ""
273   "")
275 (define_insn "ccmp<mode>"
276   [(set (match_operand:CC 1 "cc_register" "")
277         (if_then_else:CC
278           (match_operator 4 "aarch64_comparison_operator"
279            [(match_operand 0 "cc_register" "")
280             (const_int 0)])
281           (compare:CC
282             (match_operand:GPI 2 "register_operand" "r,r,r")
283             (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
284           (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
285   ""
286   "@
287    ccmp\\t%<w>2, %<w>3, %k5, %m4
288    ccmp\\t%<w>2, %3, %k5, %m4
289    ccmn\\t%<w>2, #%n3, %k5, %m4"
290   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
293 (define_insn "fccmp<mode>"
294   [(set (match_operand:CCFP 1 "cc_register" "")
295         (if_then_else:CCFP
296           (match_operator 4 "aarch64_comparison_operator"
297            [(match_operand 0 "cc_register" "")
298             (const_int 0)])
299           (compare:CCFP
300             (match_operand:GPF 2 "register_operand" "w")
301             (match_operand:GPF 3 "register_operand" "w"))
302           (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
303   "TARGET_FLOAT"
304   "fccmp\\t%<s>2, %<s>3, %k5, %m4"
305   [(set_attr "type" "fccmp<s>")]
308 (define_insn "fccmpe<mode>"
309   [(set (match_operand:CCFPE 1 "cc_register" "")
310          (if_then_else:CCFPE
311           (match_operator 4 "aarch64_comparison_operator"
312            [(match_operand 0 "cc_register" "")
313           (const_int 0)])
314            (compare:CCFPE
315             (match_operand:GPF 2 "register_operand" "w")
316             (match_operand:GPF 3 "register_operand" "w"))
317           (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
318   "TARGET_FLOAT"
319   "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
320   [(set_attr "type" "fccmp<s>")]
323 ;; Expansion of signed mod by a power of 2 using CSNEG.
324 ;; For x0 % n where n is a power of 2 produce:
325 ;; negs   x1, x0
326 ;; and    x0, x0, #(n - 1)
327 ;; and    x1, x1, #(n - 1)
328 ;; csneg  x0, x0, x1, mi
330 (define_expand "mod<mode>3"
331   [(match_operand:GPI 0 "register_operand" "")
332    (match_operand:GPI 1 "register_operand" "")
333    (match_operand:GPI 2 "const_int_operand" "")]
334   ""
335   {
336     HOST_WIDE_INT val = INTVAL (operands[2]);
338     if (val <= 0
339        || exact_log2 (val) <= 0
340        || !aarch64_bitmask_imm (val - 1, <MODE>mode))
341       FAIL;
343     rtx mask = GEN_INT (val - 1);
345     /* In the special case of x0 % 2 we can do the even shorter:
346         cmp    x0, xzr
347         and    x0, x0, 1
348         cneg   x0, x0, lt.  */
349     if (val == 2)
350       {
351         rtx masked = gen_reg_rtx (<MODE>mode);
352         rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
353         emit_insn (gen_and<mode>3 (masked, operands[1], mask));
354         rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
355         emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
356         DONE;
357       }
359     rtx neg_op = gen_reg_rtx (<MODE>mode);
360     rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
362     /* Extract the condition register and mode.  */
363     rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
364     rtx cc_reg = SET_DEST (cmp);
365     rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
367     rtx masked_pos = gen_reg_rtx (<MODE>mode);
368     emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
370     rtx masked_neg = gen_reg_rtx (<MODE>mode);
371     emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
373     emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
374                                        masked_neg, masked_pos));
375     DONE;
376   }
379 (define_insn "condjump"
380   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
381                             [(match_operand 1 "cc_register" "") (const_int 0)])
382                            (label_ref (match_operand 2 "" ""))
383                            (pc)))]
384   ""
385   {
386     if (get_attr_length (insn) == 8)
387       return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
388     else
389       return  "b%m0\\t%l2";
390   }
391   [(set_attr "type" "branch")
392    (set (attr "length")
393         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
394                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
395                       (const_int 4)
396                       (const_int 8)))
397    (set (attr "far_branch")
398         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
399                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
400                       (const_int 0)
401                       (const_int 1)))]
404 ;; For a 24-bit immediate CST we can optimize the compare for equality
405 ;; and branch sequence from:
406 ;;      mov     x0, #imm1
407 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
408 ;;      cmp     x1, x0
409 ;;      b<ne,eq> .Label
410 ;; into the shorter:
411 ;;      sub     x0, x1, #(CST & 0xfff000)
412 ;;      subs    x0, x0, #(CST & 0x000fff)
413 ;;      b<ne,eq> .Label
414 (define_insn_and_split "*compare_condjump<mode>"
415   [(set (pc) (if_then_else (EQL
416                               (match_operand:GPI 0 "register_operand" "r")
417                               (match_operand:GPI 1 "aarch64_imm24" "n"))
418                            (label_ref:P (match_operand 2 "" ""))
419                            (pc)))]
420   "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
421    && !aarch64_plus_operand (operands[1], <MODE>mode)
422    && !reload_completed"
423   "#"
424   "&& true"
425   [(const_int 0)]
426   {
427     HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
428     HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
429     rtx tmp = gen_reg_rtx (<MODE>mode);
430     emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
431     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
432     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
433     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
434     emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
435     DONE;
436   }
439 (define_expand "casesi"
440   [(match_operand:SI 0 "register_operand" "")   ; Index
441    (match_operand:SI 1 "const_int_operand" "")  ; Lower bound
442    (match_operand:SI 2 "const_int_operand" "")  ; Total range
443    (match_operand:DI 3 "" "")                   ; Table label
444    (match_operand:DI 4 "" "")]                  ; Out of range label
445   ""
446   {
447     if (operands[1] != const0_rtx)
448       {
449         rtx reg = gen_reg_rtx (SImode);
451         /* Canonical RTL says that if you have:
453            (minus (X) (CONST))
455            then this should be emitted as:
457            (plus (X) (-CONST))
459            The use of trunc_int_for_mode ensures that the resulting
460            constant can be represented in SImode, this is important
461            for the corner case where operand[1] is INT_MIN.  */
463         operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
465         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
466               (operands[1], SImode))
467           operands[1] = force_reg (SImode, operands[1]);
468         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
469         operands[0] = reg;
470       }
472     if (!aarch64_plus_operand (operands[2], SImode))
473       operands[2] = force_reg (SImode, operands[2]);
474     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
475                                                  const0_rtx),
476                                     operands[0], operands[2], operands[4]));
478     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
479     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
480                                          operands[3]));
481     DONE;
482   }
485 (define_insn "casesi_dispatch"
486   [(parallel
487     [(set (pc)
488           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
489                            (match_operand:SI 1 "register_operand" "r")]
490                         UNSPEC_CASESI)))
491      (clobber (reg:CC CC_REGNUM))
492      (clobber (match_scratch:DI 3 "=r"))
493      (clobber (match_scratch:DI 4 "=r"))
494      (use (label_ref (match_operand 2 "" "")))])]
495   ""
496   "*
497   return aarch64_output_casesi (operands);
498   "
499   [(set_attr "length" "16")
500    (set_attr "type" "branch")]
503 (define_insn "nop"
504   [(unspec[(const_int 0)] UNSPEC_NOP)]
505   ""
506   "nop"
507   [(set_attr "type" "no_insn")]
510 (define_insn "prefetch"
511   [(prefetch (match_operand:DI 0 "register_operand" "r")
512             (match_operand:QI 1 "const_int_operand" "")
513             (match_operand:QI 2 "const_int_operand" ""))]
514   ""
515   {
516     const char * pftype[2][4] = 
517     {
518       {"prfm\\tPLDL1STRM, %a0",
519        "prfm\\tPLDL3KEEP, %a0",
520        "prfm\\tPLDL2KEEP, %a0",
521        "prfm\\tPLDL1KEEP, %a0"},
522       {"prfm\\tPSTL1STRM, %a0",
523        "prfm\\tPSTL3KEEP, %a0",
524        "prfm\\tPSTL2KEEP, %a0",
525        "prfm\\tPSTL1KEEP, %a0"},
526     };
528     int locality = INTVAL (operands[2]);
530     gcc_assert (IN_RANGE (locality, 0, 3));
532     return pftype[INTVAL(operands[1])][locality];
533   }
534   [(set_attr "type" "load1")]
537 (define_insn "trap"
538   [(trap_if (const_int 1) (const_int 8))]
539   ""
540   "brk #1000"
541   [(set_attr "type" "trap")])
543 (define_expand "prologue"
544   [(clobber (const_int 0))]
545   ""
546   "
547   aarch64_expand_prologue ();
548   DONE;
549   "
552 (define_expand "epilogue"
553   [(clobber (const_int 0))]
554   ""
555   "
556   aarch64_expand_epilogue (false);
557   DONE;
558   "
561 (define_expand "sibcall_epilogue"
562   [(clobber (const_int 0))]
563   ""
564   "
565   aarch64_expand_epilogue (true);
566   DONE;
567   "
570 (define_insn "*do_return"
571   [(return)]
572   ""
573   "ret"
574   [(set_attr "type" "branch")]
577 (define_expand "return"
578   [(simple_return)]
579   "aarch64_use_return_insn_p ()"
580   ""
583 (define_insn "simple_return"
584   [(simple_return)]
585   ""
586   "ret"
587   [(set_attr "type" "branch")]
590 (define_insn "eh_return"
591   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
592     UNSPECV_EH_RETURN)]
593   ""
594   "#"
595   [(set_attr "type" "branch")]
599 (define_split
600   [(unspec_volatile [(match_operand:DI 0 "register_operand" "")]
601     UNSPECV_EH_RETURN)]
602   "reload_completed"
603   [(set (match_dup 1) (match_dup 0))]
604   {
605     operands[1] = aarch64_final_eh_return_addr ();
606   }
609 (define_insn "*cb<optab><mode>1"
610   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
611                                 (const_int 0))
612                            (label_ref (match_operand 1 "" ""))
613                            (pc)))]
614   ""
615   {
616     if (get_attr_length (insn) == 8)
617       return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
618     else
619       return "<cbz>\\t%<w>0, %l1";
620   }
621   [(set_attr "type" "branch")
622    (set (attr "length")
623         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
624                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
625                       (const_int 4)
626                       (const_int 8)))
627    (set (attr "far_branch")
628         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
629                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
630                       (const_int 0)
631                       (const_int 1)))]
634 (define_insn "*tb<optab><mode>1"
635   [(set (pc) (if_then_else
636               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
637                                     (const_int 1)
638                                     (match_operand 1 "const_int_operand" "n"))
639                    (const_int 0))
640              (label_ref (match_operand 2 "" ""))
641              (pc)))
642    (clobber (reg:CC CC_REGNUM))]
643   ""
644   {
645     if (get_attr_length (insn) == 8)
646       {
647         if (get_attr_far_branch (insn) == 1)
648           return aarch64_gen_far_branch (operands, 2, "Ltb",
649                                          "<inv_tb>\\t%<w>0, %1, ");
650         else
651           {
652             operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
653             return "tst\t%<w>0, %1\;<bcond>\t%l2";
654           }
655       }
656     else
657       return "<tbz>\t%<w>0, %1, %l2";
658   }
659   [(set_attr "type" "branch")
660    (set (attr "length")
661         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
662                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
663                       (const_int 4)
664                       (const_int 8)))
665    (set (attr "far_branch")
666         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
667                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
668                       (const_int 0)
669                       (const_int 1)))]
673 (define_insn "*cb<optab><mode>1"
674   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
675                                  (const_int 0))
676                            (label_ref (match_operand 1 "" ""))
677                            (pc)))
678    (clobber (reg:CC CC_REGNUM))]
679   ""
680   {
681     if (get_attr_length (insn) == 8)
682       {
683         if (get_attr_far_branch (insn) == 1)
684           return aarch64_gen_far_branch (operands, 1, "Ltb",
685                                          "<inv_tb>\\t%<w>0, <sizem1>, ");
686         else
687           {
688             char buf[64];
689             uint64_t val = ((uint64_t) 1)
690                 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
691             sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
692             output_asm_insn (buf, operands);
693             return "<bcond>\t%l1";
694           }
695       }
696     else
697       return "<tbz>\t%<w>0, <sizem1>, %l1";
698   }
699   [(set_attr "type" "branch")
700    (set (attr "length")
701         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
702                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
703                       (const_int 4)
704                       (const_int 8)))
705    (set (attr "far_branch")
706         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
707                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
708                       (const_int 0)
709                       (const_int 1)))]
712 ;; -------------------------------------------------------------------
713 ;; Subroutine calls and sibcalls
714 ;; -------------------------------------------------------------------
716 (define_expand "call_internal"
717   [(parallel [(call (match_operand 0 "memory_operand" "")
718                     (match_operand 1 "general_operand" ""))
719               (use (match_operand 2 "" ""))
720               (clobber (reg:DI LR_REGNUM))])])
722 (define_expand "call"
723   [(parallel [(call (match_operand 0 "memory_operand" "")
724                     (match_operand 1 "general_operand" ""))
725               (use (match_operand 2 "" ""))
726               (clobber (reg:DI LR_REGNUM))])]
727   ""
728   "
729   {
730     rtx callee, pat;
732     /* In an untyped call, we can get NULL for operand 2.  */
733     if (operands[2] == NULL)
734       operands[2] = const0_rtx;
736     /* Decide if we should generate indirect calls by loading the
737        64-bit address of the callee into a register before performing
738        the branch-and-link.  */
739     callee = XEXP (operands[0], 0);
740     if (GET_CODE (callee) == SYMBOL_REF
741         ? (aarch64_is_long_call_p (callee)
742            || aarch64_is_noplt_call_p (callee))
743         : !REG_P (callee))
744       XEXP (operands[0], 0) = force_reg (Pmode, callee);
746     pat = gen_call_internal (operands[0], operands[1], operands[2]);
747     aarch64_emit_call_insn (pat);
748     DONE;
749   }"
752 (define_insn "*call_reg"
753   [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
754          (match_operand 1 "" ""))
755    (use (match_operand 2 "" ""))
756    (clobber (reg:DI LR_REGNUM))]
757   ""
758   "blr\\t%0"
759   [(set_attr "type" "call")]
762 (define_insn "*call_symbol"
763   [(call (mem:DI (match_operand:DI 0 "" ""))
764          (match_operand 1 "" ""))
765    (use (match_operand 2 "" ""))
766    (clobber (reg:DI LR_REGNUM))]
767   "GET_CODE (operands[0]) == SYMBOL_REF
768    && !aarch64_is_long_call_p (operands[0])
769    && !aarch64_is_noplt_call_p (operands[0])"
770   "bl\\t%a0"
771   [(set_attr "type" "call")]
774 (define_expand "call_value_internal"
775   [(parallel [(set (match_operand 0 "" "")
776                    (call (match_operand 1 "memory_operand" "")
777                          (match_operand 2 "general_operand" "")))
778               (use (match_operand 3 "" ""))
779               (clobber (reg:DI LR_REGNUM))])])
781 (define_expand "call_value"
782   [(parallel [(set (match_operand 0 "" "")
783                    (call (match_operand 1 "memory_operand" "")
784                          (match_operand 2 "general_operand" "")))
785               (use (match_operand 3 "" ""))
786               (clobber (reg:DI LR_REGNUM))])]
787   ""
788   "
789   {
790     rtx callee, pat;
792     /* In an untyped call, we can get NULL for operand 3.  */
793     if (operands[3] == NULL)
794       operands[3] = const0_rtx;
796     /* Decide if we should generate indirect calls by loading the
797        64-bit address of the callee into a register before performing
798        the branch-and-link.  */
799     callee = XEXP (operands[1], 0);
800     if (GET_CODE (callee) == SYMBOL_REF
801         ? (aarch64_is_long_call_p (callee)
802            || aarch64_is_noplt_call_p (callee))
803         : !REG_P (callee))
804       XEXP (operands[1], 0) = force_reg (Pmode, callee);
806     pat = gen_call_value_internal (operands[0], operands[1], operands[2],
807                                    operands[3]);
808     aarch64_emit_call_insn (pat);
809     DONE;
810   }"
813 (define_insn "*call_value_reg"
814   [(set (match_operand 0 "" "")
815         (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
816                       (match_operand 2 "" "")))
817    (use (match_operand 3 "" ""))
818    (clobber (reg:DI LR_REGNUM))]
819   ""
820   "blr\\t%1"
821   [(set_attr "type" "call")]
825 (define_insn "*call_value_symbol"
826   [(set (match_operand 0 "" "")
827         (call (mem:DI (match_operand:DI 1 "" ""))
828               (match_operand 2 "" "")))
829    (use (match_operand 3 "" ""))
830    (clobber (reg:DI LR_REGNUM))]
831   "GET_CODE (operands[1]) == SYMBOL_REF
832    && !aarch64_is_long_call_p (operands[1])
833    && !aarch64_is_noplt_call_p (operands[1])"
834   "bl\\t%a1"
835   [(set_attr "type" "call")]
838 (define_expand "sibcall_internal"
839   [(parallel [(call (match_operand 0 "memory_operand" "")
840                     (match_operand 1 "general_operand" ""))
841               (return)
842               (use (match_operand 2 "" ""))])])
844 (define_expand "sibcall"
845   [(parallel [(call (match_operand 0 "memory_operand" "")
846                     (match_operand 1 "general_operand" ""))
847               (return)
848               (use (match_operand 2 "" ""))])]
849   ""
850   {
851     rtx pat;
852     rtx callee = XEXP (operands[0], 0);
853     if (!REG_P (callee)
854        && ((GET_CODE (callee) != SYMBOL_REF)
855            || aarch64_is_noplt_call_p (callee)))
856       XEXP (operands[0], 0) = force_reg (Pmode, callee);
858     if (operands[2] == NULL_RTX)
859       operands[2] = const0_rtx;
861     pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
862     aarch64_emit_call_insn (pat);
863     DONE;
864   }
867 (define_expand "sibcall_value_internal"
868   [(parallel [(set (match_operand 0 "" "")
869                    (call (match_operand 1 "memory_operand" "")
870                          (match_operand 2 "general_operand" "")))
871               (return)
872               (use (match_operand 3 "" ""))])])
874 (define_expand "sibcall_value"
875   [(parallel [(set (match_operand 0 "" "")
876                    (call (match_operand 1 "memory_operand" "")
877                          (match_operand 2 "general_operand" "")))
878               (return)
879               (use (match_operand 3 "" ""))])]
880   ""
881   {
882     rtx pat;
883     rtx callee = XEXP (operands[1], 0);
884     if (!REG_P (callee)
885        && ((GET_CODE (callee) != SYMBOL_REF)
886            || aarch64_is_noplt_call_p (callee)))
887       XEXP (operands[1], 0) = force_reg (Pmode, callee);
889     if (operands[3] == NULL_RTX)
890       operands[3] = const0_rtx;
892     pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
893                                       operands[3]);
894     aarch64_emit_call_insn (pat);
895     DONE;
896   }
899 (define_insn "*sibcall_insn"
900   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
901          (match_operand 1 "" ""))
902    (return)
903    (use (match_operand 2 "" ""))]
904   "SIBLING_CALL_P (insn)"
905   "@
906    br\\t%0
907    b\\t%a0"
908   [(set_attr "type" "branch, branch")]
911 (define_insn "*sibcall_value_insn"
912   [(set (match_operand 0 "" "")
913         (call (mem:DI
914                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
915               (match_operand 2 "" "")))
916    (return)
917    (use (match_operand 3 "" ""))]
918   "SIBLING_CALL_P (insn)"
919   "@
920    br\\t%1
921    b\\t%a1"
922   [(set_attr "type" "branch, branch")]
925 ;; Call subroutine returning any type.
927 (define_expand "untyped_call"
928   [(parallel [(call (match_operand 0 "")
929                     (const_int 0))
930               (match_operand 1 "")
931               (match_operand 2 "")])]
932   ""
934   int i;
936   emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
938   for (i = 0; i < XVECLEN (operands[2], 0); i++)
939     {
940       rtx set = XVECEXP (operands[2], 0, i);
941       emit_move_insn (SET_DEST (set), SET_SRC (set));
942     }
944   /* The optimizer does not know that the call sets the function value
945      registers we stored in the result block.  We avoid problems by
946      claiming that all hard registers are used and clobbered at this
947      point.  */
948   emit_insn (gen_blockage ());
949   DONE;
952 ;; -------------------------------------------------------------------
953 ;; Moves
954 ;; -------------------------------------------------------------------
956 (define_expand "mov<mode>"
957   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
958         (match_operand:SHORT 1 "general_operand" ""))]
959   ""
960   "
961     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
962       operands[1] = force_reg (<MODE>mode, operands[1]);
963   "
966 (define_insn "*mov<mode>_aarch64"
967   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,   *w,r,*w, m, m, r,*w,*w")
968         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
969   "(register_operand (operands[0], <MODE>mode)
970     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
972    switch (which_alternative)
973      {
974      case 0:
975        return "mov\t%w0, %w1";
976      case 1:
977        return "mov\t%w0, %1";
978      case 2:
979        return aarch64_output_scalar_simd_mov_immediate (operands[1],
980                                                         <MODE>mode);
981      case 3:
982        return "ldr<size>\t%w0, %1";
983      case 4:
984        return "ldr\t%<size>0, %1";
985      case 5:
986        return "str<size>\t%w1, %0";
987      case 6:
988        return "str\t%<size>1, %0";
989      case 7:
990        return "umov\t%w0, %1.<v>[0]";
991      case 8:
992        return "dup\t%0.<Vallxd>, %w1";
993      case 9:
994        return "dup\t%<Vetype>0, %1.<v>[0]";
995      default:
996        gcc_unreachable ();
997      }
999   [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
1000                      neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1001    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
1004 (define_expand "mov<mode>"
1005   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
1006         (match_operand:GPI 1 "general_operand" ""))]
1007   ""
1008   "
1009     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1010       operands[1] = force_reg (<MODE>mode, operands[1]);
1012     /* FIXME: RR we still need to fix up what we are doing with
1013        symbol_refs and other types of constants.  */
1014     if (CONSTANT_P (operands[1])
1015         && !CONST_INT_P (operands[1]))
1016      {
1017        aarch64_expand_mov_immediate (operands[0], operands[1]);
1018        DONE;
1019      }
1020   "
1023 (define_insn_and_split "*movsi_aarch64"
1024   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r  ,*w, r,*w")
1025         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1026   "(register_operand (operands[0], SImode)
1027     || aarch64_reg_or_zero (operands[1], SImode))"
1028   "@
1029    mov\\t%w0, %w1
1030    mov\\t%w0, %w1
1031    mov\\t%w0, %w1
1032    mov\\t%w0, %1
1033    #
1034    ldr\\t%w0, %1
1035    ldr\\t%s0, %1
1036    str\\t%w1, %0
1037    str\\t%s1, %0
1038    adr\\t%x0, %a1
1039    adrp\\t%x0, %A1
1040    fmov\\t%s0, %w1
1041    fmov\\t%w0, %s1
1042    fmov\\t%s0, %s1"
1043    "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1044     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1045    [(const_int 0)]
1046    "{
1047        aarch64_expand_mov_immediate (operands[0], operands[1]);
1048        DONE;
1049     }"
1050   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1051                      adr,adr,f_mcr,f_mrc,fmov")
1052    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1055 (define_insn_and_split "*movdi_aarch64"
1056   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r,  *w, r,*w,w")
1057         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1058   "(register_operand (operands[0], DImode)
1059     || aarch64_reg_or_zero (operands[1], DImode))"
1060   "@
1061    mov\\t%x0, %x1
1062    mov\\t%0, %x1
1063    mov\\t%x0, %1
1064    mov\\t%x0, %1
1065    #
1066    ldr\\t%x0, %1
1067    ldr\\t%d0, %1
1068    str\\t%x1, %0
1069    str\\t%d1, %0
1070    adr\\t%x0, %a1
1071    adrp\\t%x0, %A1
1072    fmov\\t%d0, %x1
1073    fmov\\t%x0, %d1
1074    fmov\\t%d0, %d1
1075    movi\\t%d0, %1"
1076    "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1077     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1078    [(const_int 0)]
1079    "{
1080        aarch64_expand_mov_immediate (operands[0], operands[1]);
1081        DONE;
1082     }"
1083   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1084                      adr,adr,f_mcr,f_mrc,fmov,neon_move")
1085    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1086    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1089 (define_insn "insv_imm<mode>"
1090   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1091                           (const_int 16)
1092                           (match_operand:GPI 1 "const_int_operand" "n"))
1093         (match_operand:GPI 2 "const_int_operand" "n"))]
1094   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1095    && UINTVAL (operands[1]) % 16 == 0"
1096   "movk\\t%<w>0, %X2, lsl %1"
1097   [(set_attr "type" "mov_imm")]
1100 (define_expand "movti"
1101   [(set (match_operand:TI 0 "nonimmediate_operand" "")
1102         (match_operand:TI 1 "general_operand" ""))]
1103   ""
1104   "
1105     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1106       operands[1] = force_reg (TImode, operands[1]);
1107   "
1110 (define_insn "*movti_aarch64"
1111   [(set (match_operand:TI 0
1112          "nonimmediate_operand"  "=r, *w,r ,*w,r  ,Ump,Ump,*w,m")
1113         (match_operand:TI 1
1114          "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r  ,Z  , m,*w"))]
1115   "(register_operand (operands[0], TImode)
1116     || aarch64_reg_or_zero (operands[1], TImode))"
1117   "@
1118    #
1119    #
1120    #
1121    orr\\t%0.16b, %1.16b, %1.16b
1122    ldp\\t%0, %H0, %1
1123    stp\\t%1, %H1, %0
1124    stp\\txzr, xzr, %0
1125    ldr\\t%q0, %1
1126    str\\t%q1, %0"
1127   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1128                              load2,store2,store2,f_loadd,f_stored")
1129    (set_attr "length" "8,8,8,4,4,4,4,4,4")
1130    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1131    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1134 ;; Split a TImode register-register or register-immediate move into
1135 ;; its component DImode pieces, taking care to handle overlapping
1136 ;; source and dest registers.
1137 (define_split
1138    [(set (match_operand:TI 0 "register_operand" "")
1139          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1140   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1141   [(const_int 0)]
1143   aarch64_split_128bit_move (operands[0], operands[1]);
1144   DONE;
1147 (define_expand "mov<mode>"
1148   [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1149         (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1150   ""
1151   {
1152     if (!TARGET_FLOAT)
1153       {
1154         aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1155         FAIL;
1156       }
1158     if (GET_CODE (operands[0]) == MEM
1159         && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1160               && aarch64_float_const_zero_rtx_p (operands[1])))
1161       operands[1] = force_reg (<MODE>mode, operands[1]);
1162   }
1165 (define_insn "*movhf_aarch64"
1166   [(set (match_operand:HF 0 "nonimmediate_operand" "=w, ?r,w,w,m,r,m ,r")
1167         (match_operand:HF 1 "general_operand"      "?rY, w,w,m,w,m,rY,r"))]
1168   "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1169     || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1170   "@
1171    mov\\t%0.h[0], %w1
1172    umov\\t%w0, %1.h[0]
1173    mov\\t%0.h[0], %1.h[0]
1174    ldr\\t%h0, %1
1175    str\\t%h1, %0
1176    ldrh\\t%w0, %1
1177    strh\\t%w1, %0
1178    mov\\t%w0, %w1"
1179   [(set_attr "type" "neon_from_gp,neon_to_gp,neon_move,\
1180                      f_loads,f_stores,load1,store1,mov_reg")
1181    (set_attr "simd" "yes,yes,yes,*,*,*,*,*")
1182    (set_attr "fp"   "*,*,*,yes,yes,*,*,*")]
1185 (define_insn "*movsf_aarch64"
1186   [(set (match_operand:SF 0 "nonimmediate_operand" "=w, ?r,w,w  ,w,m,r,m ,r")
1187         (match_operand:SF 1 "general_operand"      "?rY, w,w,Ufc,m,w,m,rY,r"))]
1188   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1189     || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1190   "@
1191    fmov\\t%s0, %w1
1192    fmov\\t%w0, %s1
1193    fmov\\t%s0, %s1
1194    fmov\\t%s0, %1
1195    ldr\\t%s0, %1
1196    str\\t%s1, %0
1197    ldr\\t%w0, %1
1198    str\\t%w1, %0
1199    mov\\t%w0, %w1"
1200   [(set_attr "type" "f_mcr,f_mrc,fmov,fconsts,\
1201                      f_loads,f_stores,load1,store1,mov_reg")]
1204 (define_insn "*movdf_aarch64"
1205   [(set (match_operand:DF 0 "nonimmediate_operand" "=w, ?r,w,w  ,w,m,r,m ,r")
1206         (match_operand:DF 1 "general_operand"      "?rY, w,w,Ufc,m,w,m,rY,r"))]
1207   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1208     || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1209   "@
1210    fmov\\t%d0, %x1
1211    fmov\\t%x0, %d1
1212    fmov\\t%d0, %d1
1213    fmov\\t%d0, %1
1214    ldr\\t%d0, %1
1215    str\\t%d1, %0
1216    ldr\\t%x0, %1
1217    str\\t%x1, %0
1218    mov\\t%x0, %x1"
1219   [(set_attr "type" "f_mcr,f_mrc,fmov,fconstd,\
1220                      f_loadd,f_stored,load1,store1,mov_reg")]
1223 (define_insn "*movtf_aarch64"
1224   [(set (match_operand:TF 0
1225          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump,Ump")
1226         (match_operand:TF 1
1227          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,Ump,?r ,Y"))]
1228   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1229     || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1230   "@
1231    orr\\t%0.16b, %1.16b, %1.16b
1232    #
1233    #
1234    #
1235    movi\\t%0.2d, #0
1236    fmov\\t%s0, wzr
1237    ldr\\t%q0, %1
1238    str\\t%q1, %0
1239    ldp\\t%0, %H0, %1
1240    stp\\t%1, %H1, %0
1241    stp\\txzr, xzr, %0"
1242   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1243                      f_loadd,f_stored,load2,store2,store2")
1244    (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1245    (set_attr "fp" "*,*,yes,yes,*,yes,yes,yes,*,*,*")
1246    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1249 (define_split
1250    [(set (match_operand:TF 0 "register_operand" "")
1251          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1252   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1253   [(const_int 0)]
1254   {
1255     aarch64_split_128bit_move (operands[0], operands[1]);
1256     DONE;
1257   }
1260 ;; 0 is dst
1261 ;; 1 is src
1262 ;; 2 is size of move in bytes
1263 ;; 3 is alignment
1265 (define_expand "movmemdi"
1266   [(match_operand:BLK 0 "memory_operand")
1267    (match_operand:BLK 1 "memory_operand")
1268    (match_operand:DI 2 "immediate_operand")
1269    (match_operand:DI 3 "immediate_operand")]
1270    "!STRICT_ALIGNMENT"
1272   if (aarch64_expand_movmem (operands))
1273     DONE;
1274   FAIL;
1278 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1279 ;; fairly lax checking on the second memory operation.
1280 (define_insn "load_pairsi"
1281   [(set (match_operand:SI 0 "register_operand" "=r,*w")
1282         (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1283    (set (match_operand:SI 2 "register_operand" "=r,*w")
1284         (match_operand:SI 3 "memory_operand" "m,m"))]
1285   "rtx_equal_p (XEXP (operands[3], 0),
1286                 plus_constant (Pmode,
1287                                XEXP (operands[1], 0),
1288                                GET_MODE_SIZE (SImode)))"
1289   "@
1290    ldp\\t%w0, %w2, %1
1291    ldp\\t%s0, %s2, %1"
1292   [(set_attr "type" "load2,neon_load1_2reg")
1293    (set_attr "fp" "*,yes")]
1296 (define_insn "load_pairdi"
1297   [(set (match_operand:DI 0 "register_operand" "=r,*w")
1298         (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1299    (set (match_operand:DI 2 "register_operand" "=r,*w")
1300         (match_operand:DI 3 "memory_operand" "m,m"))]
1301   "rtx_equal_p (XEXP (operands[3], 0),
1302                 plus_constant (Pmode,
1303                                XEXP (operands[1], 0),
1304                                GET_MODE_SIZE (DImode)))"
1305   "@
1306    ldp\\t%x0, %x2, %1
1307    ldp\\t%d0, %d2, %1"
1308   [(set_attr "type" "load2,neon_load1_2reg")
1309    (set_attr "fp" "*,yes")]
1313 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1314 ;; fairly lax checking on the second memory operation.
1315 (define_insn "store_pairsi"
1316   [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1317         (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1318    (set (match_operand:SI 2 "memory_operand" "=m,m")
1319         (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1320   "rtx_equal_p (XEXP (operands[2], 0),
1321                 plus_constant (Pmode,
1322                                XEXP (operands[0], 0),
1323                                GET_MODE_SIZE (SImode)))"
1324   "@
1325    stp\\t%w1, %w3, %0
1326    stp\\t%s1, %s3, %0"
1327   [(set_attr "type" "store2,neon_store1_2reg")
1328    (set_attr "fp" "*,yes")]
1331 (define_insn "store_pairdi"
1332   [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1333         (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1334    (set (match_operand:DI 2 "memory_operand" "=m,m")
1335         (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1336   "rtx_equal_p (XEXP (operands[2], 0),
1337                 plus_constant (Pmode,
1338                                XEXP (operands[0], 0),
1339                                GET_MODE_SIZE (DImode)))"
1340   "@
1341    stp\\t%x1, %x3, %0
1342    stp\\t%d1, %d3, %0"
1343   [(set_attr "type" "store2,neon_store1_2reg")
1344    (set_attr "fp" "*,yes")]
1347 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1348 ;; fairly lax checking on the second memory operation.
1349 (define_insn "load_pairsf"
1350   [(set (match_operand:SF 0 "register_operand" "=w,*r")
1351         (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1352    (set (match_operand:SF 2 "register_operand" "=w,*r")
1353         (match_operand:SF 3 "memory_operand" "m,m"))]
1354   "rtx_equal_p (XEXP (operands[3], 0),
1355                 plus_constant (Pmode,
1356                                XEXP (operands[1], 0),
1357                                GET_MODE_SIZE (SFmode)))"
1358   "@
1359    ldp\\t%s0, %s2, %1
1360    ldp\\t%w0, %w2, %1"
1361   [(set_attr "type" "neon_load1_2reg,load2")
1362    (set_attr "fp" "yes,*")]
1365 (define_insn "load_pairdf"
1366   [(set (match_operand:DF 0 "register_operand" "=w,*r")
1367         (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1368    (set (match_operand:DF 2 "register_operand" "=w,*r")
1369         (match_operand:DF 3 "memory_operand" "m,m"))]
1370   "rtx_equal_p (XEXP (operands[3], 0),
1371                 plus_constant (Pmode,
1372                                XEXP (operands[1], 0),
1373                                GET_MODE_SIZE (DFmode)))"
1374   "@
1375    ldp\\t%d0, %d2, %1
1376    ldp\\t%x0, %x2, %1"
1377   [(set_attr "type" "neon_load1_2reg,load2")
1378    (set_attr "fp" "yes,*")]
1381 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1382 ;; fairly lax checking on the second memory operation.
1383 (define_insn "store_pairsf"
1384   [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1385         (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1386    (set (match_operand:SF 2 "memory_operand" "=m,m")
1387         (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1388   "rtx_equal_p (XEXP (operands[2], 0),
1389                 plus_constant (Pmode,
1390                                XEXP (operands[0], 0),
1391                                GET_MODE_SIZE (SFmode)))"
1392   "@
1393    stp\\t%s1, %s3, %0
1394    stp\\t%w1, %w3, %0"
1395   [(set_attr "type" "neon_store1_2reg,store2")
1396    (set_attr "fp" "yes,*")]
1399 (define_insn "store_pairdf"
1400   [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1401         (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1402    (set (match_operand:DF 2 "memory_operand" "=m,m")
1403         (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1404   "rtx_equal_p (XEXP (operands[2], 0),
1405                 plus_constant (Pmode,
1406                                XEXP (operands[0], 0),
1407                                GET_MODE_SIZE (DFmode)))"
1408   "@
1409    stp\\t%d1, %d3, %0
1410    stp\\t%x1, %x3, %0"
1411   [(set_attr "type" "neon_store1_2reg,store2")
1412    (set_attr "fp" "yes,*")]
1415 ;; Load pair with post-index writeback.  This is primarily used in function
1416 ;; epilogues.
1417 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1418   [(parallel
1419     [(set (match_operand:P 0 "register_operand" "=k")
1420           (plus:P (match_operand:P 1 "register_operand" "0")
1421                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1422      (set (match_operand:GPI 2 "register_operand" "=r")
1423           (mem:GPI (match_dup 1)))
1424      (set (match_operand:GPI 3 "register_operand" "=r")
1425           (mem:GPI (plus:P (match_dup 1)
1426                    (match_operand:P 5 "const_int_operand" "n"))))])]
1427   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1428   "ldp\\t%<w>2, %<w>3, [%1], %4"
1429   [(set_attr "type" "load2")]
1432 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1433   [(parallel
1434     [(set (match_operand:P 0 "register_operand" "=k")
1435           (plus:P (match_operand:P 1 "register_operand" "0")
1436                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1437      (set (match_operand:GPF 2 "register_operand" "=w")
1438           (mem:GPF (match_dup 1)))
1439      (set (match_operand:GPF 3 "register_operand" "=w")
1440           (mem:GPF (plus:P (match_dup 1)
1441                    (match_operand:P 5 "const_int_operand" "n"))))])]
1442   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1443   "ldp\\t%<w>2, %<w>3, [%1], %4"
1444   [(set_attr "type" "neon_load1_2reg")]
1447 ;; Store pair with pre-index writeback.  This is primarily used in function
1448 ;; prologues.
1449 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1450   [(parallel
1451     [(set (match_operand:P 0 "register_operand" "=&k")
1452           (plus:P (match_operand:P 1 "register_operand" "0")
1453                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1454      (set (mem:GPI (plus:P (match_dup 0)
1455                    (match_dup 4)))
1456           (match_operand:GPI 2 "register_operand" "r"))
1457      (set (mem:GPI (plus:P (match_dup 0)
1458                    (match_operand:P 5 "const_int_operand" "n")))
1459           (match_operand:GPI 3 "register_operand" "r"))])]
1460   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1461   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1462   [(set_attr "type" "store2")]
1465 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1466   [(parallel
1467     [(set (match_operand:P 0 "register_operand" "=&k")
1468           (plus:P (match_operand:P 1 "register_operand" "0")
1469                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1470      (set (mem:GPF (plus:P (match_dup 0)
1471                    (match_dup 4)))
1472           (match_operand:GPF 2 "register_operand" "w"))
1473      (set (mem:GPF (plus:P (match_dup 0)
1474                    (match_operand:P 5 "const_int_operand" "n")))
1475           (match_operand:GPF 3 "register_operand" "w"))])]
1476   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1477   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1478   [(set_attr "type" "neon_store1_2reg<q>")]
1481 ;; -------------------------------------------------------------------
1482 ;; Sign/Zero extension
1483 ;; -------------------------------------------------------------------
1485 (define_expand "<optab>sidi2"
1486   [(set (match_operand:DI 0 "register_operand")
1487         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1488   ""
1491 (define_insn "*extendsidi2_aarch64"
1492   [(set (match_operand:DI 0 "register_operand" "=r,r")
1493         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1494   ""
1495   "@
1496    sxtw\t%0, %w1
1497    ldrsw\t%0, %1"
1498   [(set_attr "type" "extend,load1")]
1501 (define_insn "*load_pair_extendsidi2_aarch64"
1502   [(set (match_operand:DI 0 "register_operand" "=r")
1503         (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1504    (set (match_operand:DI 2 "register_operand" "=r")
1505         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1506   "rtx_equal_p (XEXP (operands[3], 0),
1507                 plus_constant (Pmode,
1508                                XEXP (operands[1], 0),
1509                                GET_MODE_SIZE (SImode)))"
1510   "ldpsw\\t%0, %2, %1"
1511   [(set_attr "type" "load2")]
1514 (define_insn "*zero_extendsidi2_aarch64"
1515   [(set (match_operand:DI 0 "register_operand" "=r,r")
1516         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1517   ""
1518   "@
1519    uxtw\t%0, %w1
1520    ldr\t%w0, %1"
1521   [(set_attr "type" "extend,load1")]
1524 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1525   [(set (match_operand:DI 0 "register_operand" "=r")
1526         (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1527    (set (match_operand:DI 2 "register_operand" "=r")
1528         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1529   "rtx_equal_p (XEXP (operands[3], 0),
1530                 plus_constant (Pmode,
1531                                XEXP (operands[1], 0),
1532                                GET_MODE_SIZE (SImode)))"
1533   "ldp\\t%w0, %w2, %1"
1534   [(set_attr "type" "load2")]
1537 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1538   [(set (match_operand:GPI 0 "register_operand")
1539         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1540   ""
1543 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1544   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1545         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1546   ""
1547   "@
1548    sxt<SHORT:size>\t%<GPI:w>0, %w1
1549    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1550   [(set_attr "type" "extend,load1")]
1553 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1554   [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1555         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1556   ""
1557   "@
1558    uxt<SHORT:size>\t%<GPI:w>0, %w1
1559    ldr<SHORT:size>\t%w0, %1
1560    ldr\t%<SHORT:size>0, %1"
1561   [(set_attr "type" "extend,load1,load1")]
1564 (define_expand "<optab>qihi2"
1565   [(set (match_operand:HI 0 "register_operand")
1566         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1567   ""
1570 (define_insn "*<optab>qihi2_aarch64"
1571   [(set (match_operand:HI 0 "register_operand" "=r,r")
1572         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1573   ""
1574   "@
1575    <su>xtb\t%w0, %w1
1576    <ldrxt>b\t%w0, %1"
1577   [(set_attr "type" "extend,load1")]
1580 ;; -------------------------------------------------------------------
1581 ;; Simple arithmetic
1582 ;; -------------------------------------------------------------------
1584 (define_expand "add<mode>3"
1585   [(set
1586     (match_operand:GPI 0 "register_operand" "")
1587     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1588               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1589   ""
1591   if (aarch64_pluslong_strict_immedate (operands[2], <MODE>mode))
1592     {
1593       /* Give CSE the opportunity to share this constant across additions.  */
1594       if (!cse_not_expected && can_create_pseudo_p ())
1595         operands[2] = force_reg (<MODE>mode, operands[2]);
1597       /* Split will refuse to operate on a modification to the stack pointer.
1598          Aid the prologue and epilogue expanders by splitting this now.  */
1599       else if (reload_completed && operands[0] == stack_pointer_rtx)
1600         {
1601           HOST_WIDE_INT i = INTVAL (operands[2]);
1602           HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1603           emit_insn (gen_rtx_SET (operands[0],
1604                                   gen_rtx_PLUS (<MODE>mode, operands[1],
1605                                                 GEN_INT (i - s))));
1606           operands[1] = operands[0];
1607           operands[2] = GEN_INT (s);
1608         }
1609     }
1612 (define_insn "*add<mode>3_aarch64"
1613   [(set
1614     (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1615     (plus:GPI
1616      (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1617      (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1618   ""
1619   "@
1620   add\\t%<w>0, %<w>1, %2
1621   add\\t%<w>0, %<w>1, %<w>2
1622   add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1623   sub\\t%<w>0, %<w>1, #%n2
1624   #"
1625   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1626    (set_attr "simd" "*,*,yes,*,*")]
1629 ;; zero_extend version of above
1630 (define_insn "*addsi3_aarch64_uxtw"
1631   [(set
1632     (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1633     (zero_extend:DI
1634      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1635               (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1636   ""
1637   "@
1638   add\\t%w0, %w1, %2
1639   add\\t%w0, %w1, %w2
1640   sub\\t%w0, %w1, #%n2
1641   #"
1642   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1645 ;; If there's a free register, and we can load the constant with a
1646 ;; single instruction, do so.  This has a chance to improve scheduling.
1647 (define_peephole2
1648   [(match_scratch:GPI 3 "r")
1649    (set (match_operand:GPI 0 "register_operand")
1650         (plus:GPI
1651           (match_operand:GPI 1 "register_operand")
1652           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1653   "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1654   [(set (match_dup 3) (match_dup 2))
1655    (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1658 (define_peephole2
1659   [(match_scratch:SI 3 "r")
1660    (set (match_operand:DI 0 "register_operand")
1661         (zero_extend:DI
1662           (plus:SI
1663             (match_operand:SI 1 "register_operand")
1664             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1665   "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1666   [(set (match_dup 3) (match_dup 2))
1667    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1670 ;; After peephole2 has had a chance to run, split any remaining long
1671 ;; additions into two add immediates.
1672 (define_split
1673   [(set (match_operand:GPI 0 "register_operand")
1674         (plus:GPI
1675           (match_operand:GPI 1 "register_operand")
1676           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1677   "epilogue_completed"
1678   [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1679    (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1680   {
1681     HOST_WIDE_INT i = INTVAL (operands[2]);
1682     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1683     operands[3] = GEN_INT (i - s);
1684     operands[4] = GEN_INT (s);
1685   }
1688 (define_split
1689   [(set (match_operand:DI 0 "register_operand")
1690         (zero_extend:DI
1691           (plus:SI
1692             (match_operand:SI 1 "register_operand")
1693             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1694   "epilogue_completed"
1695   [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1696    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1697   {
1698     HOST_WIDE_INT i = INTVAL (operands[2]);
1699     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1700     operands[3] = GEN_INT (i - s);
1701     operands[4] = GEN_INT (s);
1702     operands[5] = gen_lowpart (SImode, operands[0]);
1703   }
1706 (define_expand "addti3"
1707   [(set (match_operand:TI 0 "register_operand" "")
1708         (plus:TI (match_operand:TI 1 "register_operand" "")
1709                  (match_operand:TI 2 "register_operand" "")))]
1710   ""
1712   rtx low = gen_reg_rtx (DImode);
1713   emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1714                                   gen_lowpart (DImode, operands[2])));
1716   rtx high = gen_reg_rtx (DImode);
1717   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1718                                  gen_highpart (DImode, operands[2])));
1720   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1721   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1722   DONE;
1725 (define_insn "add<mode>3_compare0"
1726   [(set (reg:CC_NZ CC_REGNUM)
1727         (compare:CC_NZ
1728          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1729                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1730          (const_int 0)))
1731    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1732         (plus:GPI (match_dup 1) (match_dup 2)))]
1733   ""
1734   "@
1735   adds\\t%<w>0, %<w>1, %<w>2
1736   adds\\t%<w>0, %<w>1, %2
1737   subs\\t%<w>0, %<w>1, #%n2"
1738   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1741 ;; zero_extend version of above
1742 (define_insn "*addsi3_compare0_uxtw"
1743   [(set (reg:CC_NZ CC_REGNUM)
1744         (compare:CC_NZ
1745          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1746                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1747          (const_int 0)))
1748    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1749         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1750   ""
1751   "@
1752   adds\\t%w0, %w1, %w2
1753   adds\\t%w0, %w1, %2
1754   subs\\t%w0, %w1, #%n2"
1755   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1758 (define_insn "*add<mode>3_compareC_cconly_imm"
1759   [(set (reg:CC_C CC_REGNUM)
1760         (ne:CC_C
1761           (plus:<DWI>
1762             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1763             (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1764           (zero_extend:<DWI>
1765             (plus:GPI
1766               (match_dup 0)
1767               (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1768   "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1769                                  <MODE>mode, operands[1])"
1770   "@
1771   cmn\\t%<w>0, %<w>1
1772   cmp\\t%<w>0, #%n1"
1773   [(set_attr "type" "alus_imm")]
1776 (define_insn "*add<mode>3_compareC_cconly"
1777   [(set (reg:CC_C CC_REGNUM)
1778         (ne:CC_C
1779           (plus:<DWI>
1780             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1781             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1782           (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1783   ""
1784   "cmn\\t%<w>0, %<w>1"
1785   [(set_attr "type" "alus_sreg")]
1788 (define_insn "*add<mode>3_compareC_imm"
1789   [(set (reg:CC_C CC_REGNUM)
1790         (ne:CC_C
1791           (plus:<DWI>
1792             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1793             (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1794           (zero_extend:<DWI>
1795             (plus:GPI
1796               (match_dup 1)
1797               (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1798    (set (match_operand:GPI 0 "register_operand" "=r,r")
1799         (plus:GPI (match_dup 1) (match_dup 2)))]
1800   "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1801                                  <MODE>mode, operands[2])"
1802   "@
1803   adds\\t%<w>0, %<w>1, %<w>2
1804   subs\\t%<w>0, %<w>1, #%n2"
1805   [(set_attr "type" "alus_imm")]
1808 (define_insn "add<mode>3_compareC"
1809   [(set (reg:CC_C CC_REGNUM)
1810         (ne:CC_C
1811           (plus:<DWI>
1812             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1813             (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1814           (zero_extend:<DWI>
1815             (plus:GPI (match_dup 1) (match_dup 2)))))
1816    (set (match_operand:GPI 0 "register_operand" "=r")
1817         (plus:GPI (match_dup 1) (match_dup 2)))]
1818   ""
1819   "adds\\t%<w>0, %<w>1, %<w>2"
1820   [(set_attr "type" "alus_sreg")]
1823 (define_insn "*adds_shift_imm_<mode>"
1824   [(set (reg:CC_NZ CC_REGNUM)
1825         (compare:CC_NZ
1826          (plus:GPI (ASHIFT:GPI 
1827                     (match_operand:GPI 1 "register_operand" "r")
1828                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1829                    (match_operand:GPI 3 "register_operand" "r"))
1830          (const_int 0)))
1831    (set (match_operand:GPI 0 "register_operand" "=r")
1832         (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1833                   (match_dup 3)))]
1834   ""
1835   "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1836   [(set_attr "type" "alus_shift_imm")]
1839 (define_insn "*subs_shift_imm_<mode>"
1840   [(set (reg:CC_NZ CC_REGNUM)
1841         (compare:CC_NZ
1842          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1843                     (ASHIFT:GPI
1844                      (match_operand:GPI 2 "register_operand" "r")
1845                      (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1846          (const_int 0)))
1847    (set (match_operand:GPI 0 "register_operand" "=r")
1848         (minus:GPI (match_dup 1)
1849                    (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1850   ""
1851   "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1852   [(set_attr "type" "alus_shift_imm")]
1855 (define_insn "*adds_mul_imm_<mode>"
1856   [(set (reg:CC_NZ CC_REGNUM)
1857         (compare:CC_NZ
1858          (plus:GPI (mult:GPI
1859                     (match_operand:GPI 1 "register_operand" "r")
1860                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1861                    (match_operand:GPI 3 "register_operand" "r"))
1862          (const_int 0)))
1863    (set (match_operand:GPI 0 "register_operand" "=r")
1864         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1865                   (match_dup 3)))]
1866   ""
1867   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1868   [(set_attr "type" "alus_shift_imm")]
1871 (define_insn "*subs_mul_imm_<mode>"
1872   [(set (reg:CC_NZ CC_REGNUM)
1873         (compare:CC_NZ
1874          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1875                     (mult:GPI
1876                      (match_operand:GPI 2 "register_operand" "r")
1877                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1878          (const_int 0)))
1879    (set (match_operand:GPI 0 "register_operand" "=r")
1880         (minus:GPI (match_dup 1)
1881                    (mult:GPI (match_dup 2) (match_dup 3))))]
1882   ""
1883   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1884   [(set_attr "type" "alus_shift_imm")]
1887 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1888   [(set (reg:CC_NZ CC_REGNUM)
1889         (compare:CC_NZ
1890          (plus:GPI
1891           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1892           (match_operand:GPI 2 "register_operand" "r"))
1893         (const_int 0)))
1894    (set (match_operand:GPI 0 "register_operand" "=r")
1895         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1896   ""
1897   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1898   [(set_attr "type" "alus_ext")]
1901 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1902   [(set (reg:CC_NZ CC_REGNUM)
1903         (compare:CC_NZ
1904          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1905                     (ANY_EXTEND:GPI
1906                      (match_operand:ALLX 2 "register_operand" "r")))
1907         (const_int 0)))
1908    (set (match_operand:GPI 0 "register_operand" "=r")
1909         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1910   ""
1911   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1912   [(set_attr "type" "alus_ext")]
1915 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1916   [(set (reg:CC_NZ CC_REGNUM)
1917         (compare:CC_NZ
1918          (plus:GPI (ashift:GPI 
1919                     (ANY_EXTEND:GPI 
1920                      (match_operand:ALLX 1 "register_operand" "r"))
1921                     (match_operand 2 "aarch64_imm3" "Ui3"))
1922                    (match_operand:GPI 3 "register_operand" "r"))
1923          (const_int 0)))
1924    (set (match_operand:GPI 0 "register_operand" "=rk")
1925         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1926                               (match_dup 2))
1927                   (match_dup 3)))]
1928   ""
1929   "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1930   [(set_attr "type" "alus_ext")]
1933 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1934   [(set (reg:CC_NZ CC_REGNUM)
1935         (compare:CC_NZ
1936          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1937                     (ashift:GPI 
1938                      (ANY_EXTEND:GPI
1939                       (match_operand:ALLX 2 "register_operand" "r"))
1940                      (match_operand 3 "aarch64_imm3" "Ui3")))
1941          (const_int 0)))
1942    (set (match_operand:GPI 0 "register_operand" "=rk")
1943         (minus:GPI (match_dup 1)
1944                    (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1945                                (match_dup 3))))]
1946   ""
1947   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1948   [(set_attr "type" "alus_ext")]
1951 (define_insn "*adds_<optab><mode>_multp2"
1952   [(set (reg:CC_NZ CC_REGNUM)
1953         (compare:CC_NZ
1954          (plus:GPI (ANY_EXTRACT:GPI
1955                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1956                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1957                     (match_operand 3 "const_int_operand" "n")
1958                     (const_int 0))
1959                    (match_operand:GPI 4 "register_operand" "r"))
1960         (const_int 0)))
1961    (set (match_operand:GPI 0 "register_operand" "=r")
1962         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1963                                    (match_dup 3)
1964                                    (const_int 0))
1965                   (match_dup 4)))]
1966   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1967   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1968   [(set_attr "type" "alus_ext")]
1971 (define_insn "*subs_<optab><mode>_multp2"
1972   [(set (reg:CC_NZ CC_REGNUM)
1973         (compare:CC_NZ
1974          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1975                     (ANY_EXTRACT:GPI
1976                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1977                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1978                      (match_operand 3 "const_int_operand" "n")
1979                      (const_int 0)))
1980         (const_int 0)))
1981    (set (match_operand:GPI 0 "register_operand" "=r")
1982         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1983                                   (mult:GPI (match_dup 1) (match_dup 2))
1984                                   (match_dup 3)
1985                                   (const_int 0))))]
1986   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1987   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1988   [(set_attr "type" "alus_ext")]
1991 (define_insn "*add<mode>3nr_compare0"
1992   [(set (reg:CC_NZ CC_REGNUM)
1993         (compare:CC_NZ
1994          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1995                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
1996          (const_int 0)))]
1997   ""
1998   "@
1999   cmn\\t%<w>0, %<w>1
2000   cmn\\t%<w>0, %1
2001   cmp\\t%<w>0, #%n1"
2002   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2005 (define_insn "*compare_neg<mode>"
2006   [(set (reg:CC_Z CC_REGNUM)
2007         (compare:CC_Z
2008          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2009          (match_operand:GPI 1 "register_operand" "r")))]
2010   ""
2011   "cmn\\t%<w>1, %<w>0"
2012   [(set_attr "type" "alus_sreg")]
2015 (define_insn "*add_<shift>_<mode>"
2016   [(set (match_operand:GPI 0 "register_operand" "=r")
2017         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2018                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2019                   (match_operand:GPI 3 "register_operand" "r")))]
2020   ""
2021   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2022   [(set_attr "type" "alu_shift_imm")]
2025 ;; zero_extend version of above
2026 (define_insn "*add_<shift>_si_uxtw"
2027   [(set (match_operand:DI 0 "register_operand" "=r")
2028         (zero_extend:DI
2029          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2030                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2031                   (match_operand:SI 3 "register_operand" "r"))))]
2032   ""
2033   "add\\t%w0, %w3, %w1, <shift> %2"
2034   [(set_attr "type" "alu_shift_imm")]
2037 (define_insn "*add_mul_imm_<mode>"
2038   [(set (match_operand:GPI 0 "register_operand" "=r")
2039         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2040                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2041                   (match_operand:GPI 3 "register_operand" "r")))]
2042   ""
2043   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2044   [(set_attr "type" "alu_shift_imm")]
2047 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2048   [(set (match_operand:GPI 0 "register_operand" "=rk")
2049         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2050                   (match_operand:GPI 2 "register_operand" "r")))]
2051   ""
2052   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2053   [(set_attr "type" "alu_ext")]
2056 ;; zero_extend version of above
2057 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2058   [(set (match_operand:DI 0 "register_operand" "=rk")
2059         (zero_extend:DI
2060          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2061                   (match_operand:GPI 2 "register_operand" "r"))))]
2062   ""
2063   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2064   [(set_attr "type" "alu_ext")]
2067 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2068   [(set (match_operand:GPI 0 "register_operand" "=rk")
2069         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2070                                (match_operand:ALLX 1 "register_operand" "r"))
2071                               (match_operand 2 "aarch64_imm3" "Ui3"))
2072                   (match_operand:GPI 3 "register_operand" "r")))]
2073   ""
2074   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2075   [(set_attr "type" "alu_ext")]
2078 ;; zero_extend version of above
2079 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2080   [(set (match_operand:DI 0 "register_operand" "=rk")
2081         (zero_extend:DI
2082          (plus:SI (ashift:SI (ANY_EXTEND:SI
2083                               (match_operand:SHORT 1 "register_operand" "r"))
2084                              (match_operand 2 "aarch64_imm3" "Ui3"))
2085                   (match_operand:SI 3 "register_operand" "r"))))]
2086   ""
2087   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2088   [(set_attr "type" "alu_ext")]
2091 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2092   [(set (match_operand:GPI 0 "register_operand" "=rk")
2093         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2094                              (match_operand:ALLX 1 "register_operand" "r"))
2095                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2096                   (match_operand:GPI 3 "register_operand" "r")))]
2097   ""
2098   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2099   [(set_attr "type" "alu_ext")]
2102 ;; zero_extend version of above
2103 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2104   [(set (match_operand:DI 0 "register_operand" "=rk")
2105         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2106                              (match_operand:SHORT 1 "register_operand" "r"))
2107                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2108                   (match_operand:SI 3 "register_operand" "r"))))]
2109   ""
2110   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2111   [(set_attr "type" "alu_ext")]
2114 (define_insn "*add_<optab><mode>_multp2"
2115   [(set (match_operand:GPI 0 "register_operand" "=rk")
2116         (plus:GPI (ANY_EXTRACT:GPI
2117                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2118                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2119                    (match_operand 3 "const_int_operand" "n")
2120                    (const_int 0))
2121                   (match_operand:GPI 4 "register_operand" "r")))]
2122   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2123   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2124   [(set_attr "type" "alu_ext")]
2127 ;; zero_extend version of above
2128 (define_insn "*add_<optab>si_multp2_uxtw"
2129   [(set (match_operand:DI 0 "register_operand" "=rk")
2130         (zero_extend:DI
2131          (plus:SI (ANY_EXTRACT:SI
2132                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2133                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2134                    (match_operand 3 "const_int_operand" "n")
2135                    (const_int 0))
2136                   (match_operand:SI 4 "register_operand" "r"))))]
2137   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2138   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2139   [(set_attr "type" "alu_ext")]
2142 (define_expand "add<mode>3_carryin"
2143   [(set (match_operand:GPI 0 "register_operand")
2144         (plus:GPI
2145           (plus:GPI
2146             (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2147             (match_operand:GPI 1 "aarch64_reg_or_zero"))
2148           (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2149    ""
2150    ""
2153 ;; Note that add with carry with two zero inputs is matched by cset,
2154 ;; and that add with carry with one zero input is matched by cinc.
2156 (define_insn "*add<mode>3_carryin"
2157   [(set (match_operand:GPI 0 "register_operand" "=r")
2158         (plus:GPI
2159           (plus:GPI
2160             (match_operand:GPI 3 "aarch64_carry_operation" "")
2161             (match_operand:GPI 1 "register_operand" "r"))
2162           (match_operand:GPI 2 "register_operand" "r")))]
2163    ""
2164    "adc\\t%<w>0, %<w>1, %<w>2"
2165   [(set_attr "type" "adc_reg")]
2168 ;; zero_extend version of above
2169 (define_insn "*addsi3_carryin_uxtw"
2170   [(set (match_operand:DI 0 "register_operand" "=r")
2171         (zero_extend:DI
2172           (plus:SI
2173             (plus:SI
2174               (match_operand:SI 3 "aarch64_carry_operation" "")
2175               (match_operand:SI 1 "register_operand" "r"))
2176             (match_operand:SI 2 "register_operand" "r"))))]
2177    ""
2178    "adc\\t%w0, %w1, %w2"
2179   [(set_attr "type" "adc_reg")]
2182 (define_insn "*add_uxt<mode>_shift2"
2183   [(set (match_operand:GPI 0 "register_operand" "=rk")
2184         (plus:GPI (and:GPI
2185                    (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2186                                (match_operand 2 "aarch64_imm3" "Ui3"))
2187                    (match_operand 3 "const_int_operand" "n"))
2188                   (match_operand:GPI 4 "register_operand" "r")))]
2189   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2190   "*
2191   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2192                                            INTVAL (operands[3])));
2193   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2194   [(set_attr "type" "alu_ext")]
2197 ;; zero_extend version of above
2198 (define_insn "*add_uxtsi_shift2_uxtw"
2199   [(set (match_operand:DI 0 "register_operand" "=rk")
2200         (zero_extend:DI
2201          (plus:SI (and:SI
2202                    (ashift:SI (match_operand:SI 1 "register_operand" "r")
2203                               (match_operand 2 "aarch64_imm3" "Ui3"))
2204                    (match_operand 3 "const_int_operand" "n"))
2205                   (match_operand:SI 4 "register_operand" "r"))))]
2206   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2207   "*
2208   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2209                                            INTVAL (operands[3])));
2210   return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2211   [(set_attr "type" "alu_ext")]
2214 (define_insn "*add_uxt<mode>_multp2"
2215   [(set (match_operand:GPI 0 "register_operand" "=rk")
2216         (plus:GPI (and:GPI
2217                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2218                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2219                    (match_operand 3 "const_int_operand" "n"))
2220                   (match_operand:GPI 4 "register_operand" "r")))]
2221   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2222   "*
2223   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2224                                            INTVAL (operands[3])));
2225   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2226   [(set_attr "type" "alu_ext")]
2229 ;; zero_extend version of above
2230 (define_insn "*add_uxtsi_multp2_uxtw"
2231   [(set (match_operand:DI 0 "register_operand" "=rk")
2232         (zero_extend:DI
2233          (plus:SI (and:SI
2234                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2235                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2236                    (match_operand 3 "const_int_operand" "n"))
2237                   (match_operand:SI 4 "register_operand" "r"))))]
2238   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2239   "*
2240   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2241                                            INTVAL (operands[3])));
2242   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2243   [(set_attr "type" "alu_ext")]
2246 (define_insn "subsi3"
2247   [(set (match_operand:SI 0 "register_operand" "=rk")
2248         (minus:SI (match_operand:SI 1 "register_operand" "rk")
2249                   (match_operand:SI 2 "register_operand" "r")))]
2250   ""
2251   "sub\\t%w0, %w1, %w2"
2252   [(set_attr "type" "alu_sreg")]
2255 ;; zero_extend version of above
2256 (define_insn "*subsi3_uxtw"
2257   [(set (match_operand:DI 0 "register_operand" "=rk")
2258         (zero_extend:DI
2259          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2260                    (match_operand:SI 2 "register_operand" "r"))))]
2261   ""
2262   "sub\\t%w0, %w1, %w2"
2263   [(set_attr "type" "alu_sreg")]
2266 (define_insn "subdi3"
2267   [(set (match_operand:DI 0 "register_operand" "=rk,w")
2268         (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2269                   (match_operand:DI 2 "register_operand" "r,w")))]
2270   ""
2271   "@
2272    sub\\t%x0, %x1, %x2
2273    sub\\t%d0, %d1, %d2"
2274   [(set_attr "type" "alu_sreg, neon_sub")
2275    (set_attr "simd" "*,yes")]
2278 (define_expand "subti3"
2279   [(set (match_operand:TI 0 "register_operand" "")
2280         (minus:TI (match_operand:TI 1 "register_operand" "")
2281                   (match_operand:TI 2 "register_operand" "")))]
2282   ""
2284   rtx low = gen_reg_rtx (DImode);
2285   emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2286                                   gen_lowpart (DImode, operands[2])));
2288   rtx high = gen_reg_rtx (DImode);
2289   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2290                                  gen_highpart (DImode, operands[2])));
2292   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2293   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2294   DONE;
2297 (define_insn "*sub<mode>3_compare0"
2298   [(set (reg:CC_NZ CC_REGNUM)
2299         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2300                                   (match_operand:GPI 2 "register_operand" "r"))
2301                        (const_int 0)))
2302    (set (match_operand:GPI 0 "register_operand" "=r")
2303         (minus:GPI (match_dup 1) (match_dup 2)))]
2304   ""
2305   "subs\\t%<w>0, %<w>1, %<w>2"
2306   [(set_attr "type" "alus_sreg")]
2309 ;; zero_extend version of above
2310 (define_insn "*subsi3_compare0_uxtw"
2311   [(set (reg:CC_NZ CC_REGNUM)
2312         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2313                                  (match_operand:SI 2 "register_operand" "r"))
2314                        (const_int 0)))
2315    (set (match_operand:DI 0 "register_operand" "=r")
2316         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2317   ""
2318   "subs\\t%w0, %w1, %w2"
2319   [(set_attr "type" "alus_sreg")]
2322 (define_insn "sub<mode>3_compare1"
2323   [(set (reg:CC CC_REGNUM)
2324         (compare:CC
2325           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2326           (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2327    (set (match_operand:GPI 0 "register_operand" "=r")
2328         (minus:GPI (match_dup 1) (match_dup 2)))]
2329   ""
2330   "subs\\t%<w>0, %<w>1, %<w>2"
2331   [(set_attr "type" "alus_sreg")]
2334 (define_insn "*sub_<shift>_<mode>"
2335   [(set (match_operand:GPI 0 "register_operand" "=r")
2336         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2337                    (ASHIFT:GPI
2338                     (match_operand:GPI 1 "register_operand" "r")
2339                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2340   ""
2341   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2342   [(set_attr "type" "alu_shift_imm")]
2345 ;; zero_extend version of above
2346 (define_insn "*sub_<shift>_si_uxtw"
2347   [(set (match_operand:DI 0 "register_operand" "=r")
2348         (zero_extend:DI
2349          (minus:SI (match_operand:SI 3 "register_operand" "r")
2350                    (ASHIFT:SI
2351                     (match_operand:SI 1 "register_operand" "r")
2352                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2353   ""
2354   "sub\\t%w0, %w3, %w1, <shift> %2"
2355   [(set_attr "type" "alu_shift_imm")]
2358 (define_insn "*sub_mul_imm_<mode>"
2359   [(set (match_operand:GPI 0 "register_operand" "=r")
2360         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2361                    (mult:GPI
2362                     (match_operand:GPI 1 "register_operand" "r")
2363                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2364   ""
2365   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2366   [(set_attr "type" "alu_shift_imm")]
2369 ;; zero_extend version of above
2370 (define_insn "*sub_mul_imm_si_uxtw"
2371   [(set (match_operand:DI 0 "register_operand" "=r")
2372         (zero_extend:DI
2373          (minus:SI (match_operand:SI 3 "register_operand" "r")
2374                    (mult:SI
2375                     (match_operand:SI 1 "register_operand" "r")
2376                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2377   ""
2378   "sub\\t%w0, %w3, %w1, lsl %p2"
2379   [(set_attr "type" "alu_shift_imm")]
2382 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2383   [(set (match_operand:GPI 0 "register_operand" "=rk")
2384         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2385                    (ANY_EXTEND:GPI
2386                     (match_operand:ALLX 2 "register_operand" "r"))))]
2387   ""
2388   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2389   [(set_attr "type" "alu_ext")]
2392 ;; zero_extend version of above
2393 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2394   [(set (match_operand:DI 0 "register_operand" "=rk")
2395         (zero_extend:DI
2396          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2397                    (ANY_EXTEND:SI
2398                     (match_operand:SHORT 2 "register_operand" "r")))))]
2399   ""
2400   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2401   [(set_attr "type" "alu_ext")]
2404 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2405   [(set (match_operand:GPI 0 "register_operand" "=rk")
2406         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2407                    (ashift:GPI (ANY_EXTEND:GPI
2408                                 (match_operand:ALLX 2 "register_operand" "r"))
2409                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
2410   ""
2411   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2412   [(set_attr "type" "alu_ext")]
2415 ;; zero_extend version of above
2416 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2417   [(set (match_operand:DI 0 "register_operand" "=rk")
2418         (zero_extend:DI
2419          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2420                    (ashift:SI (ANY_EXTEND:SI
2421                                (match_operand:SHORT 2 "register_operand" "r"))
2422                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
2423   ""
2424   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2425   [(set_attr "type" "alu_ext")]
2428 (define_insn "*sub_<optab><mode>_multp2"
2429   [(set (match_operand:GPI 0 "register_operand" "=rk")
2430         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2431                    (ANY_EXTRACT:GPI
2432                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2433                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2434                     (match_operand 3 "const_int_operand" "n")
2435                     (const_int 0))))]
2436   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2437   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2438   [(set_attr "type" "alu_ext")]
2441 ;; zero_extend version of above
2442 (define_insn "*sub_<optab>si_multp2_uxtw"
2443   [(set (match_operand:DI 0 "register_operand" "=rk")
2444         (zero_extend:DI
2445          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2446                    (ANY_EXTRACT:SI
2447                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2448                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2449                     (match_operand 3 "const_int_operand" "n")
2450                     (const_int 0)))))]
2451   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2452   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2453   [(set_attr "type" "alu_ext")]
2456 ;; The hardware description is op1 + ~op2 + C.
2457 ;;                           = op1 + (-op2 + 1) + (1 - !C)
2458 ;;                           = op1 - op2 - 1 + 1 - !C
2459 ;;                           = op1 - op2 - !C.
2460 ;; We describe the latter.
2462 (define_insn "*sub<mode>3_carryin0"
2463   [(set (match_operand:GPI 0 "register_operand" "=r")
2464         (minus:GPI
2465           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2466           (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2467    ""
2468    "sbc\\t%<w>0, %<w>1, <w>zr"
2469   [(set_attr "type" "adc_reg")]
2472 ;; zero_extend version of the above
2473 (define_insn "*subsi3_carryin_uxtw"
2474   [(set (match_operand:DI 0 "register_operand" "=r")
2475         (zero_extend:DI
2476           (minus:SI
2477             (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2478             (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2479    ""
2480    "sbc\\t%w0, %w1, wzr"
2481   [(set_attr "type" "adc_reg")]
2484 (define_expand "sub<mode>3_carryin"
2485   [(set (match_operand:GPI 0 "register_operand")
2486         (minus:GPI
2487           (minus:GPI
2488             (match_operand:GPI 1 "aarch64_reg_or_zero")
2489             (match_operand:GPI 2 "register_operand"))
2490           (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2491    ""
2492    ""
2495 (define_insn "*sub<mode>3_carryin"
2496   [(set (match_operand:GPI 0 "register_operand" "=r")
2497         (minus:GPI
2498           (minus:GPI
2499             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2500             (match_operand:GPI 2 "register_operand" "r"))
2501           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2503    ""
2504    "sbc\\t%<w>0, %<w>1, %<w>2"
2505   [(set_attr "type" "adc_reg")]
2508 ;; zero_extend version of the above
2509 (define_insn "*subsi3_carryin_uxtw"
2510   [(set (match_operand:DI 0 "register_operand" "=r")
2511         (zero_extend:DI
2512           (minus:SI
2513             (minus:SI
2514               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2515               (match_operand:SI 2 "register_operand" "r"))
2516             (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2518    ""
2519    "sbc\\t%w0, %w1, %w2"
2520   [(set_attr "type" "adc_reg")]
2523 (define_insn "*sub<mode>3_carryin_alt"
2524   [(set (match_operand:GPI 0 "register_operand" "=r")
2525         (minus:GPI
2526           (minus:GPI
2527             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2528             (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2529           (match_operand:GPI 2 "register_operand" "r")))]
2530    ""
2531    "sbc\\t%<w>0, %<w>1, %<w>2"
2532   [(set_attr "type" "adc_reg")]
2535 ;; zero_extend version of the above
2536 (define_insn "*subsi3_carryin_alt_uxtw"
2537   [(set (match_operand:DI 0 "register_operand" "=r")
2538         (zero_extend:DI
2539           (minus:SI
2540             (minus:SI
2541               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2542               (match_operand:SI 3 "aarch64_borrow_operation" ""))
2543             (match_operand:SI 2 "register_operand" "r"))))]
2544    ""
2545    "sbc\\t%w0, %w1, %w2"
2546   [(set_attr "type" "adc_reg")]
2549 (define_insn "*sub_uxt<mode>_shift2"
2550   [(set (match_operand:GPI 0 "register_operand" "=rk")
2551         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2552                    (and:GPI
2553                     (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2554                                 (match_operand 2 "aarch64_imm3" "Ui3"))
2555                     (match_operand 3 "const_int_operand" "n"))))]
2556   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2557   "*
2558   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2559                                            INTVAL (operands[3])));
2560   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2561   [(set_attr "type" "alu_ext")]
2564 ;; zero_extend version of above
2565 (define_insn "*sub_uxtsi_shift2_uxtw"
2566   [(set (match_operand:DI 0 "register_operand" "=rk")
2567         (zero_extend:DI
2568          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2569                    (and:SI
2570                     (ashift:SI (match_operand:SI 1 "register_operand" "r")
2571                                (match_operand 2 "aarch64_imm3" "Ui3"))
2572                     (match_operand 3 "const_int_operand" "n")))))]
2573   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2574   "*
2575   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2576                                            INTVAL (operands[3])));
2577   return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2578   [(set_attr "type" "alu_ext")]
2581 (define_insn "*sub_uxt<mode>_multp2"
2582   [(set (match_operand:GPI 0 "register_operand" "=rk")
2583         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2584                    (and:GPI
2585                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2586                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2587                     (match_operand 3 "const_int_operand" "n"))))]
2588   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2589   "*
2590   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2591                                            INTVAL (operands[3])));
2592   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2593   [(set_attr "type" "alu_ext")]
2596 ;; zero_extend version of above
2597 (define_insn "*sub_uxtsi_multp2_uxtw"
2598   [(set (match_operand:DI 0 "register_operand" "=rk")
2599         (zero_extend:DI
2600          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2601                    (and:SI
2602                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2603                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2604                     (match_operand 3 "const_int_operand" "n")))))]
2605   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2606   "*
2607   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2608                                            INTVAL (operands[3])));
2609   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2610   [(set_attr "type" "alu_ext")]
2613 (define_expand "abs<mode>2"
2614   [(match_operand:GPI 0 "register_operand" "")
2615    (match_operand:GPI 1 "register_operand" "")]
2616   ""
2617   {
2618     rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2619     rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2620     emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2621     DONE;
2622   }
2625 (define_insn "neg<mode>2"
2626   [(set (match_operand:GPI 0 "register_operand" "=r,w")
2627         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2628   ""
2629   "@
2630    neg\\t%<w>0, %<w>1
2631    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2632   [(set_attr "type" "alu_sreg, neon_neg<q>")
2633    (set_attr "simd" "*,yes")]
2636 ;; zero_extend version of above
2637 (define_insn "*negsi2_uxtw"
2638   [(set (match_operand:DI 0 "register_operand" "=r")
2639         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2640   ""
2641   "neg\\t%w0, %w1"
2642   [(set_attr "type" "alu_sreg")]
2645 (define_insn "*ngc<mode>"
2646   [(set (match_operand:GPI 0 "register_operand" "=r")
2647         (minus:GPI
2648           (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2649           (match_operand:GPI 1 "register_operand" "r")))]
2650   ""
2651   "ngc\\t%<w>0, %<w>1"
2652   [(set_attr "type" "adc_reg")]
2655 (define_insn "*ngcsi_uxtw"
2656   [(set (match_operand:DI 0 "register_operand" "=r")
2657         (zero_extend:DI
2658           (minus:SI
2659             (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2660             (match_operand:SI 1 "register_operand" "r"))))]
2661   ""
2662   "ngc\\t%w0, %w1"
2663   [(set_attr "type" "adc_reg")]
2666 (define_insn "neg<mode>2_compare0"
2667   [(set (reg:CC_NZ CC_REGNUM)
2668         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2669                        (const_int 0)))
2670    (set (match_operand:GPI 0 "register_operand" "=r")
2671         (neg:GPI (match_dup 1)))]
2672   ""
2673   "negs\\t%<w>0, %<w>1"
2674   [(set_attr "type" "alus_sreg")]
2677 ;; zero_extend version of above
2678 (define_insn "*negsi2_compare0_uxtw"
2679   [(set (reg:CC_NZ CC_REGNUM)
2680         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2681                        (const_int 0)))
2682    (set (match_operand:DI 0 "register_operand" "=r")
2683         (zero_extend:DI (neg:SI (match_dup 1))))]
2684   ""
2685   "negs\\t%w0, %w1"
2686   [(set_attr "type" "alus_sreg")]
2689 (define_insn "*neg_<shift><mode>3_compare0"
2690   [(set (reg:CC_NZ CC_REGNUM)
2691         (compare:CC_NZ
2692          (neg:GPI (ASHIFT:GPI
2693                    (match_operand:GPI 1 "register_operand" "r")
2694                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2695          (const_int 0)))
2696    (set (match_operand:GPI 0 "register_operand" "=r")
2697         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2698   ""
2699   "negs\\t%<w>0, %<w>1, <shift> %2"
2700   [(set_attr "type" "alus_shift_imm")]
2703 (define_insn "*neg_<shift>_<mode>2"
2704   [(set (match_operand:GPI 0 "register_operand" "=r")
2705         (neg:GPI (ASHIFT:GPI
2706                   (match_operand:GPI 1 "register_operand" "r")
2707                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2708   ""
2709   "neg\\t%<w>0, %<w>1, <shift> %2"
2710   [(set_attr "type" "alu_shift_imm")]
2713 ;; zero_extend version of above
2714 (define_insn "*neg_<shift>_si2_uxtw"
2715   [(set (match_operand:DI 0 "register_operand" "=r")
2716         (zero_extend:DI
2717          (neg:SI (ASHIFT:SI
2718                   (match_operand:SI 1 "register_operand" "r")
2719                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2720   ""
2721   "neg\\t%w0, %w1, <shift> %2"
2722   [(set_attr "type" "alu_shift_imm")]
2725 (define_insn "*neg_mul_imm_<mode>2"
2726   [(set (match_operand:GPI 0 "register_operand" "=r")
2727         (neg:GPI (mult:GPI
2728                   (match_operand:GPI 1 "register_operand" "r")
2729                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2730   ""
2731   "neg\\t%<w>0, %<w>1, lsl %p2"
2732   [(set_attr "type" "alu_shift_imm")]
2735 ;; zero_extend version of above
2736 (define_insn "*neg_mul_imm_si2_uxtw"
2737   [(set (match_operand:DI 0 "register_operand" "=r")
2738         (zero_extend:DI
2739          (neg:SI (mult:SI
2740                   (match_operand:SI 1 "register_operand" "r")
2741                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2742   ""
2743   "neg\\t%w0, %w1, lsl %p2"
2744   [(set_attr "type" "alu_shift_imm")]
2747 (define_insn "mul<mode>3"
2748   [(set (match_operand:GPI 0 "register_operand" "=r")
2749         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2750                   (match_operand:GPI 2 "register_operand" "r")))]
2751   ""
2752   "mul\\t%<w>0, %<w>1, %<w>2"
2753   [(set_attr "type" "mul")]
2756 ;; zero_extend version of above
2757 (define_insn "*mulsi3_uxtw"
2758   [(set (match_operand:DI 0 "register_operand" "=r")
2759         (zero_extend:DI
2760          (mult:SI (match_operand:SI 1 "register_operand" "r")
2761                   (match_operand:SI 2 "register_operand" "r"))))]
2762   ""
2763   "mul\\t%w0, %w1, %w2"
2764   [(set_attr "type" "mul")]
2767 (define_insn "madd<mode>"
2768   [(set (match_operand:GPI 0 "register_operand" "=r")
2769         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2770                             (match_operand:GPI 2 "register_operand" "r"))
2771                   (match_operand:GPI 3 "register_operand" "r")))]
2772   ""
2773   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2774   [(set_attr "type" "mla")]
2777 ;; zero_extend version of above
2778 (define_insn "*maddsi_uxtw"
2779   [(set (match_operand:DI 0 "register_operand" "=r")
2780         (zero_extend:DI
2781          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2782                            (match_operand:SI 2 "register_operand" "r"))
2783                   (match_operand:SI 3 "register_operand" "r"))))]
2784   ""
2785   "madd\\t%w0, %w1, %w2, %w3"
2786   [(set_attr "type" "mla")]
2789 (define_insn "*msub<mode>"
2790   [(set (match_operand:GPI 0 "register_operand" "=r")
2791         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2792                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2793                              (match_operand:GPI 2 "register_operand" "r"))))]
2795   ""
2796   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2797   [(set_attr "type" "mla")]
2800 ;; zero_extend version of above
2801 (define_insn "*msubsi_uxtw"
2802   [(set (match_operand:DI 0 "register_operand" "=r")
2803         (zero_extend:DI
2804          (minus:SI (match_operand:SI 3 "register_operand" "r")
2805                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2806                             (match_operand:SI 2 "register_operand" "r")))))]
2808   ""
2809   "msub\\t%w0, %w1, %w2, %w3"
2810   [(set_attr "type" "mla")]
2813 (define_insn "*mul<mode>_neg"
2814   [(set (match_operand:GPI 0 "register_operand" "=r")
2815         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2816                   (match_operand:GPI 2 "register_operand" "r")))]
2818   ""
2819   "mneg\\t%<w>0, %<w>1, %<w>2"
2820   [(set_attr "type" "mul")]
2823 ;; zero_extend version of above
2824 (define_insn "*mulsi_neg_uxtw"
2825   [(set (match_operand:DI 0 "register_operand" "=r")
2826         (zero_extend:DI
2827          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2828                   (match_operand:SI 2 "register_operand" "r"))))]
2830   ""
2831   "mneg\\t%w0, %w1, %w2"
2832   [(set_attr "type" "mul")]
2835 (define_insn "<su_optab>mulsidi3"
2836   [(set (match_operand:DI 0 "register_operand" "=r")
2837         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2838                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2839   ""
2840   "<su>mull\\t%0, %w1, %w2"
2841   [(set_attr "type" "<su>mull")]
2844 (define_insn "<su_optab>maddsidi4"
2845   [(set (match_operand:DI 0 "register_operand" "=r")
2846         (plus:DI (mult:DI
2847                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2848                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2849                  (match_operand:DI 3 "register_operand" "r")))]
2850   ""
2851   "<su>maddl\\t%0, %w1, %w2, %3"
2852   [(set_attr "type" "<su>mlal")]
2855 (define_insn "<su_optab>msubsidi4"
2856   [(set (match_operand:DI 0 "register_operand" "=r")
2857         (minus:DI
2858          (match_operand:DI 3 "register_operand" "r")
2859          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2860                   (ANY_EXTEND:DI
2861                    (match_operand:SI 2 "register_operand" "r")))))]
2862   ""
2863   "<su>msubl\\t%0, %w1, %w2, %3"
2864   [(set_attr "type" "<su>mlal")]
2867 (define_insn "*<su_optab>mulsidi_neg"
2868   [(set (match_operand:DI 0 "register_operand" "=r")
2869         (mult:DI (neg:DI
2870                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2871                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2872   ""
2873   "<su>mnegl\\t%0, %w1, %w2"
2874   [(set_attr "type" "<su>mull")]
2877 (define_expand "<su_optab>mulditi3"
2878   [(set (match_operand:TI 0 "register_operand")
2879         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2880                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2881   ""
2883   rtx low = gen_reg_rtx (DImode);
2884   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2886   rtx high = gen_reg_rtx (DImode);
2887   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2889   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2890   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2891   DONE;
2894 ;; The default expansion of multi3 using umuldi3_highpart will perform
2895 ;; the additions in an order that fails to combine into two madd insns.
2896 (define_expand "multi3"
2897   [(set (match_operand:TI 0 "register_operand")
2898         (mult:TI (match_operand:TI 1 "register_operand")
2899                  (match_operand:TI 2 "register_operand")))]
2900   ""
2902   rtx l0 = gen_reg_rtx (DImode);
2903   rtx l1 = gen_lowpart (DImode, operands[1]);
2904   rtx l2 = gen_lowpart (DImode, operands[2]);
2905   rtx h0 = gen_reg_rtx (DImode);
2906   rtx h1 = gen_highpart (DImode, operands[1]);
2907   rtx h2 = gen_highpart (DImode, operands[2]);
2909   emit_insn (gen_muldi3 (l0, l1, l2));
2910   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2911   emit_insn (gen_madddi (h0, h1, l2, h0));
2912   emit_insn (gen_madddi (h0, l1, h2, h0));
2914   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2915   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2916   DONE;
2919 (define_insn "<su>muldi3_highpart"
2920   [(set (match_operand:DI 0 "register_operand" "=r")
2921         (truncate:DI
2922          (lshiftrt:TI
2923           (mult:TI
2924            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2925            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2926           (const_int 64))))]
2927   ""
2928   "<su>mulh\\t%0, %1, %2"
2929   [(set_attr "type" "<su>mull")]
2932 (define_insn "<su_optab>div<mode>3"
2933   [(set (match_operand:GPI 0 "register_operand" "=r")
2934         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2935                      (match_operand:GPI 2 "register_operand" "r")))]
2936   ""
2937   "<su>div\\t%<w>0, %<w>1, %<w>2"
2938   [(set_attr "type" "<su>div")]
2941 ;; zero_extend version of above
2942 (define_insn "*<su_optab>divsi3_uxtw"
2943   [(set (match_operand:DI 0 "register_operand" "=r")
2944         (zero_extend:DI
2945          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2946                      (match_operand:SI 2 "register_operand" "r"))))]
2947   ""
2948   "<su>div\\t%w0, %w1, %w2"
2949   [(set_attr "type" "<su>div")]
2952 ;; -------------------------------------------------------------------
2953 ;; Comparison insns
2954 ;; -------------------------------------------------------------------
2956 (define_insn "cmp<mode>"
2957   [(set (reg:CC CC_REGNUM)
2958         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2959                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2960   ""
2961   "@
2962    cmp\\t%<w>0, %<w>1
2963    cmp\\t%<w>0, %1
2964    cmn\\t%<w>0, #%n1"
2965   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2968 (define_insn "fcmp<mode>"
2969   [(set (reg:CCFP CC_REGNUM)
2970         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2971                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2972    "TARGET_FLOAT"
2973    "@
2974     fcmp\\t%<s>0, #0.0
2975     fcmp\\t%<s>0, %<s>1"
2976   [(set_attr "type" "fcmp<s>")]
2979 (define_insn "fcmpe<mode>"
2980   [(set (reg:CCFPE CC_REGNUM)
2981         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2982                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2983    "TARGET_FLOAT"
2984    "@
2985     fcmpe\\t%<s>0, #0.0
2986     fcmpe\\t%<s>0, %<s>1"
2987   [(set_attr "type" "fcmp<s>")]
2990 (define_insn "*cmp_swp_<shift>_reg<mode>"
2991   [(set (reg:CC_SWP CC_REGNUM)
2992         (compare:CC_SWP (ASHIFT:GPI
2993                          (match_operand:GPI 0 "register_operand" "r")
2994                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2995                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2996   ""
2997   "cmp\\t%<w>2, %<w>0, <shift> %1"
2998   [(set_attr "type" "alus_shift_imm")]
3001 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3002   [(set (reg:CC_SWP CC_REGNUM)
3003         (compare:CC_SWP (ANY_EXTEND:GPI
3004                          (match_operand:ALLX 0 "register_operand" "r"))
3005                         (match_operand:GPI 1 "register_operand" "r")))]
3006   ""
3007   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3008   [(set_attr "type" "alus_ext")]
3011 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3012   [(set (reg:CC_SWP CC_REGNUM)
3013         (compare:CC_SWP (ashift:GPI
3014                          (ANY_EXTEND:GPI
3015                           (match_operand:ALLX 0 "register_operand" "r"))
3016                          (match_operand 1 "aarch64_imm3" "Ui3"))
3017         (match_operand:GPI 2 "register_operand" "r")))]
3018   ""
3019   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3020   [(set_attr "type" "alus_ext")]
3023 ;; -------------------------------------------------------------------
3024 ;; Store-flag and conditional select insns
3025 ;; -------------------------------------------------------------------
3027 (define_expand "cstore<mode>4"
3028   [(set (match_operand:SI 0 "register_operand" "")
3029         (match_operator:SI 1 "aarch64_comparison_operator"
3030          [(match_operand:GPI 2 "register_operand" "")
3031           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3032   ""
3033   "
3034   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3035                                       operands[3]);
3036   operands[3] = const0_rtx;
3037   "
3040 (define_expand "cstorecc4"
3041   [(set (match_operand:SI 0 "register_operand")
3042        (match_operator 1 "aarch64_comparison_operator_mode"
3043         [(match_operand 2 "cc_register")
3044          (match_operand 3 "const0_operand")]))]
3045   ""
3047   emit_insn (gen_rtx_SET (operands[0], operands[1]));
3048   DONE;
3052 (define_expand "cstore<mode>4"
3053   [(set (match_operand:SI 0 "register_operand" "")
3054         (match_operator:SI 1 "aarch64_comparison_operator_mode"
3055          [(match_operand:GPF 2 "register_operand" "")
3056           (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3057   ""
3058   "
3059   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3060                                       operands[3]);
3061   operands[3] = const0_rtx;
3062   "
3065 (define_insn "aarch64_cstore<mode>"
3066   [(set (match_operand:ALLI 0 "register_operand" "=r")
3067         (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3068          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3069   ""
3070   "cset\\t%<w>0, %m1"
3071   [(set_attr "type" "csel")]
3074 ;; For a 24-bit immediate CST we can optimize the compare for equality
3075 ;; and branch sequence from:
3076 ;;      mov     x0, #imm1
3077 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
3078 ;;      cmp     x1, x0
3079 ;;      cset    x2, <ne,eq>
3080 ;; into the shorter:
3081 ;;      sub     x0, x1, #(CST & 0xfff000)
3082 ;;      subs    x0, x0, #(CST & 0x000fff)
3083 ;;      cset x2, <ne, eq>.
3084 (define_insn_and_split "*compare_cstore<mode>_insn"
3085   [(set (match_operand:GPI 0 "register_operand" "=r")
3086          (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3087                   (match_operand:GPI 2 "aarch64_imm24" "n")))]
3088   "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3089    && !aarch64_plus_operand (operands[2], <MODE>mode)
3090    && !reload_completed"
3091   "#"
3092   "&& true"
3093   [(const_int 0)]
3094   {
3095     HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3096     HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3097     rtx tmp = gen_reg_rtx (<MODE>mode);
3098     emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3099     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3100     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3101     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3102     emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3103     DONE;
3104   }
3105   [(set_attr "type" "csel")]
3108 ;; zero_extend version of the above
3109 (define_insn "*cstoresi_insn_uxtw"
3110   [(set (match_operand:DI 0 "register_operand" "=r")
3111         (zero_extend:DI
3112          (match_operator:SI 1 "aarch64_comparison_operator_mode"
3113           [(match_operand 2 "cc_register" "") (const_int 0)])))]
3114   ""
3115   "cset\\t%w0, %m1"
3116   [(set_attr "type" "csel")]
3119 (define_insn "cstore<mode>_neg"
3120   [(set (match_operand:ALLI 0 "register_operand" "=r")
3121         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3122                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
3123   ""
3124   "csetm\\t%<w>0, %m1"
3125   [(set_attr "type" "csel")]
3128 ;; zero_extend version of the above
3129 (define_insn "*cstoresi_neg_uxtw"
3130   [(set (match_operand:DI 0 "register_operand" "=r")
3131         (zero_extend:DI
3132          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3133                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3134   ""
3135   "csetm\\t%w0, %m1"
3136   [(set_attr "type" "csel")]
3139 (define_expand "cmov<mode>6"
3140   [(set (match_operand:GPI 0 "register_operand" "")
3141         (if_then_else:GPI
3142          (match_operator 1 "aarch64_comparison_operator"
3143           [(match_operand:GPI 2 "register_operand" "")
3144            (match_operand:GPI 3 "aarch64_plus_operand" "")])
3145          (match_operand:GPI 4 "register_operand" "")
3146          (match_operand:GPI 5 "register_operand" "")))]
3147   ""
3148   "
3149   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3150                                       operands[3]);
3151   operands[3] = const0_rtx;
3152   "
3155 (define_expand "cmov<mode>6"
3156   [(set (match_operand:GPF 0 "register_operand" "")
3157         (if_then_else:GPF
3158          (match_operator 1 "aarch64_comparison_operator"
3159           [(match_operand:GPF 2 "register_operand" "")
3160            (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3161          (match_operand:GPF 4 "register_operand" "")
3162          (match_operand:GPF 5 "register_operand" "")))]
3163   ""
3164   "
3165   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3166                                       operands[3]);
3167   operands[3] = const0_rtx;
3168   "
3171 (define_insn "*cmov<mode>_insn"
3172   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3173         (if_then_else:ALLI
3174          (match_operator 1 "aarch64_comparison_operator"
3175           [(match_operand 2 "cc_register" "") (const_int 0)])
3176          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3177          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3178   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3179      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3180   ;; Final two alternatives should be unreachable, but included for completeness
3181   "@
3182    csel\\t%<w>0, %<w>3, %<w>4, %m1
3183    csinv\\t%<w>0, %<w>3, <w>zr, %m1
3184    csinv\\t%<w>0, %<w>4, <w>zr, %M1
3185    csinc\\t%<w>0, %<w>3, <w>zr, %m1
3186    csinc\\t%<w>0, %<w>4, <w>zr, %M1
3187    mov\\t%<w>0, -1
3188    mov\\t%<w>0, 1"
3189   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3192 ;; zero_extend version of above
3193 (define_insn "*cmovsi_insn_uxtw"
3194   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3195         (zero_extend:DI
3196          (if_then_else:SI
3197           (match_operator 1 "aarch64_comparison_operator"
3198            [(match_operand 2 "cc_register" "") (const_int 0)])
3199           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3200           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3201   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3202      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3203   ;; Final two alternatives should be unreachable, but included for completeness
3204   "@
3205    csel\\t%w0, %w3, %w4, %m1
3206    csinv\\t%w0, %w3, wzr, %m1
3207    csinv\\t%w0, %w4, wzr, %M1
3208    csinc\\t%w0, %w3, wzr, %m1
3209    csinc\\t%w0, %w4, wzr, %M1
3210    mov\\t%w0, -1
3211    mov\\t%w0, 1"
3212   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3215 (define_insn "*cmovdi_insn_uxtw"
3216   [(set (match_operand:DI 0 "register_operand" "=r")
3217         (if_then_else:DI
3218          (match_operator 1 "aarch64_comparison_operator"
3219           [(match_operand 2 "cc_register" "") (const_int 0)])
3220          (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3221          (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3222   ""
3223   "csel\\t%w0, %w3, %w4, %m1"
3224   [(set_attr "type" "csel")]
3227 (define_insn "*cmov<mode>_insn"
3228   [(set (match_operand:GPF 0 "register_operand" "=w")
3229         (if_then_else:GPF
3230          (match_operator 1 "aarch64_comparison_operator"
3231           [(match_operand 2 "cc_register" "") (const_int 0)])
3232          (match_operand:GPF 3 "register_operand" "w")
3233          (match_operand:GPF 4 "register_operand" "w")))]
3234   "TARGET_FLOAT"
3235   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3236   [(set_attr "type" "fcsel")]
3239 (define_expand "mov<mode>cc"
3240   [(set (match_operand:ALLI 0 "register_operand" "")
3241         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3242                            (match_operand:ALLI 2 "register_operand" "")
3243                            (match_operand:ALLI 3 "register_operand" "")))]
3244   ""
3245   {
3246     rtx ccreg;
3247     enum rtx_code code = GET_CODE (operands[1]);
3249     if (code == UNEQ || code == LTGT)
3250       FAIL;
3252     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3253                                      XEXP (operands[1], 1));
3254     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3255   }
3258 (define_expand "mov<GPF:mode><GPI:mode>cc"
3259   [(set (match_operand:GPI 0 "register_operand" "")
3260         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3261                           (match_operand:GPF 2 "register_operand" "")
3262                           (match_operand:GPF 3 "register_operand" "")))]
3263   ""
3264   {
3265     rtx ccreg;
3266     enum rtx_code code = GET_CODE (operands[1]);
3268     if (code == UNEQ || code == LTGT)
3269       FAIL;
3271     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3272                                   XEXP (operands[1], 1));
3273     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3274   }
3277 (define_expand "mov<mode>cc"
3278   [(set (match_operand:GPF 0 "register_operand" "")
3279         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3280                           (match_operand:GPF 2 "register_operand" "")
3281                           (match_operand:GPF 3 "register_operand" "")))]
3282   ""
3283   {
3284     rtx ccreg;
3285     enum rtx_code code = GET_CODE (operands[1]);
3287     if (code == UNEQ || code == LTGT)
3288       FAIL;
3290     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3291                                   XEXP (operands[1], 1));
3292     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3293   }
3296 (define_expand "<neg_not_op><mode>cc"
3297   [(set (match_operand:GPI 0 "register_operand" "")
3298         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3299                           (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3300                           (match_operand:GPI 3 "register_operand" "")))]
3301   ""
3302   {
3303     rtx ccreg;
3304     enum rtx_code code = GET_CODE (operands[1]);
3306     if (code == UNEQ || code == LTGT)
3307       FAIL;
3309     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3310                                       XEXP (operands[1], 1));
3311     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3312   }
3315 ;; CRC32 instructions.
3316 (define_insn "aarch64_<crc_variant>"
3317   [(set (match_operand:SI 0 "register_operand" "=r")
3318         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3319                     (match_operand:<crc_mode> 2 "register_operand" "r")]
3320          CRC))]
3321   "TARGET_CRC32"
3322   {
3323     if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3324       return "<crc_variant>\\t%w0, %w1, %x2";
3325     else
3326       return "<crc_variant>\\t%w0, %w1, %w2";
3327   }
3328   [(set_attr "type" "crc")]
3331 (define_insn "*csinc2<mode>_insn"
3332   [(set (match_operand:GPI 0 "register_operand" "=r")
3333         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3334                   (match_operand:GPI 1 "register_operand" "r")))]
3335   ""
3336   "cinc\\t%<w>0, %<w>1, %m2"
3337   [(set_attr "type" "csel")]
3340 (define_insn "csinc3<mode>_insn"
3341   [(set (match_operand:GPI 0 "register_operand" "=r")
3342         (if_then_else:GPI
3343           (match_operand 1 "aarch64_comparison_operation" "")
3344           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3345                     (const_int 1))
3346           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3347   ""
3348   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3349   [(set_attr "type" "csel")]
3352 (define_insn "*csinv3<mode>_insn"
3353   [(set (match_operand:GPI 0 "register_operand" "=r")
3354         (if_then_else:GPI
3355           (match_operand 1 "aarch64_comparison_operation" "")
3356           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3357           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3358   ""
3359   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3360   [(set_attr "type" "csel")]
3363 (define_insn "csneg3_uxtw_insn"
3364   [(set (match_operand:DI 0 "register_operand" "=r")
3365         (zero_extend:DI
3366           (if_then_else:SI
3367             (match_operand 1 "aarch64_comparison_operation" "")
3368             (neg:SI (match_operand:SI 2 "register_operand" "r"))
3369             (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3370   ""
3371   "csneg\\t%w0, %w3, %w2, %M1"
3372   [(set_attr "type" "csel")]
3375 (define_insn "csneg3<mode>_insn"
3376   [(set (match_operand:GPI 0 "register_operand" "=r")
3377         (if_then_else:GPI
3378           (match_operand 1 "aarch64_comparison_operation" "")
3379           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3380           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3381   ""
3382   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3383   [(set_attr "type" "csel")]
3386 ;; -------------------------------------------------------------------
3387 ;; Logical operations
3388 ;; -------------------------------------------------------------------
3390 (define_insn "<optab><mode>3"
3391   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3392         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3393                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3394   ""
3395   "@
3396   <logical>\\t%<w>0, %<w>1, %<w>2
3397   <logical>\\t%<w>0, %<w>1, %2
3398   <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3399   [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3400    (set_attr "simd" "*,*,yes")]
3403 ;; zero_extend version of above
3404 (define_insn "*<optab>si3_uxtw"
3405   [(set (match_operand:DI 0 "register_operand" "=r,rk")
3406         (zero_extend:DI
3407          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3408                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3409   ""
3410   "<logical>\\t%w0, %w1, %w2"
3411   [(set_attr "type" "logic_reg,logic_imm")]
3414 (define_insn "*and<mode>3_compare0"
3415   [(set (reg:CC_NZ CC_REGNUM)
3416         (compare:CC_NZ
3417          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3418                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3419          (const_int 0)))
3420    (set (match_operand:GPI 0 "register_operand" "=r,r")
3421         (and:GPI (match_dup 1) (match_dup 2)))]
3422   ""
3423   "ands\\t%<w>0, %<w>1, %<w>2"
3424   [(set_attr "type" "logics_reg,logics_imm")]
3427 ;; zero_extend version of above
3428 (define_insn "*andsi3_compare0_uxtw"
3429   [(set (reg:CC_NZ CC_REGNUM)
3430         (compare:CC_NZ
3431          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3432                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3433          (const_int 0)))
3434    (set (match_operand:DI 0 "register_operand" "=r,r")
3435         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3436   ""
3437   "ands\\t%w0, %w1, %w2"
3438   [(set_attr "type" "logics_reg,logics_imm")]
3441 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3442   [(set (reg:CC_NZ CC_REGNUM)
3443         (compare:CC_NZ
3444          (and:GPI (SHIFT:GPI
3445                    (match_operand:GPI 1 "register_operand" "r")
3446                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3447                   (match_operand:GPI 3 "register_operand" "r"))
3448          (const_int 0)))
3449    (set (match_operand:GPI 0 "register_operand" "=r")
3450         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3451   ""
3452   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3453   [(set_attr "type" "logics_shift_imm")]
3456 ;; zero_extend version of above
3457 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3458   [(set (reg:CC_NZ CC_REGNUM)
3459         (compare:CC_NZ
3460          (and:SI (SHIFT:SI
3461                   (match_operand:SI 1 "register_operand" "r")
3462                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3463                  (match_operand:SI 3 "register_operand" "r"))
3464          (const_int 0)))
3465    (set (match_operand:DI 0 "register_operand" "=r")
3466         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3467                                 (match_dup 3))))]
3468   ""
3469   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3470   [(set_attr "type" "logics_shift_imm")]
3473 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3474   [(set (match_operand:GPI 0 "register_operand" "=r")
3475         (LOGICAL:GPI (SHIFT:GPI
3476                       (match_operand:GPI 1 "register_operand" "r")
3477                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3478                      (match_operand:GPI 3 "register_operand" "r")))]
3479   ""
3480   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3481   [(set_attr "type" "logic_shift_imm")]
3484 (define_insn "*<optab>_rol<mode>3"
3485   [(set (match_operand:GPI 0 "register_operand" "=r")
3486         (LOGICAL:GPI (rotate:GPI
3487                       (match_operand:GPI 1 "register_operand" "r")
3488                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3489                      (match_operand:GPI 3 "register_operand" "r")))]
3490   ""
3491   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3492   [(set_attr "type" "logic_shift_imm")]
3495 ;; zero_extend versions of above
3496 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3497   [(set (match_operand:DI 0 "register_operand" "=r")
3498         (zero_extend:DI
3499          (LOGICAL: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   ""
3504   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3505   [(set_attr "type" "logic_shift_imm")]
3508 (define_insn "*<optab>_rolsi3_uxtw"
3509   [(set (match_operand:DI 0 "register_operand" "=r")
3510         (zero_extend:DI
3511          (LOGICAL:SI (rotate:SI
3512                       (match_operand:SI 1 "register_operand" "r")
3513                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3514                      (match_operand:SI 3 "register_operand" "r"))))]
3515   ""
3516   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3517   [(set_attr "type" "logic_shift_imm")]
3520 (define_insn "one_cmpl<mode>2"
3521   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3522         (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3523   ""
3524   "@
3525   mvn\\t%<w>0, %<w>1
3526   mvn\\t%0.8b, %1.8b"
3527   [(set_attr "type" "logic_reg,neon_logic")
3528    (set_attr "simd" "*,yes")]
3531 (define_insn "*one_cmpl_<optab><mode>2"
3532   [(set (match_operand:GPI 0 "register_operand" "=r")
3533         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3534                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3535   ""
3536   "mvn\\t%<w>0, %<w>1, <shift> %2"
3537   [(set_attr "type" "logic_shift_imm")]
3540 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3542 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3543   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3544         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3545                      (match_operand:GPI 2 "register_operand" "r,w")))]
3546   ""
3547   "@
3548   <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3549   <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3550   [(set_attr "type" "logic_reg,neon_logic")
3551    (set_attr "simd" "*,yes")]
3554 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3555   [(set (match_operand:DI 0 "register_operand" "=r")
3556         (zero_extend:DI
3557           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3558                        (match_operand:SI 2 "register_operand" "r"))))]
3559   ""
3560   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3561   [(set_attr "type" "logic_reg")]
3564 (define_insn "*xor_one_cmplsidi3_ze"
3565   [(set (match_operand:DI 0 "register_operand" "=r")
3566         (zero_extend:DI
3567           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3568                           (match_operand:SI 2 "register_operand" "r")))))]
3569   ""
3570   "eon\\t%w0, %w1, %w2"
3571   [(set_attr "type" "logic_reg")]
3574 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3575 ;; eon does not operate on SIMD registers so the vector variant must be split.
3576 (define_insn_and_split "*xor_one_cmpl<mode>3"
3577   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3578         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3579                           (match_operand:GPI 2 "register_operand" "r,w"))))]
3580   ""
3581   "@
3582   eon\\t%<w>0, %<w>1, %<w>2
3583   #"
3584   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3585   [(set (match_operand:GPI 0 "register_operand" "=w")
3586         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3587                  (match_operand:GPI 2 "register_operand" "w")))
3588    (set (match_dup 0) (not:GPI (match_dup 0)))]
3589   ""
3590   [(set_attr "type" "logic_reg,multiple")
3591    (set_attr "simd" "*,yes")]
3594 (define_insn "*and_one_cmpl<mode>3_compare0"
3595   [(set (reg:CC_NZ CC_REGNUM)
3596         (compare:CC_NZ
3597          (and:GPI (not:GPI
3598                    (match_operand:GPI 1 "register_operand" "r"))
3599                   (match_operand:GPI 2 "register_operand" "r"))
3600          (const_int 0)))
3601    (set (match_operand:GPI 0 "register_operand" "=r")
3602         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3603   ""
3604   "bics\\t%<w>0, %<w>2, %<w>1"
3605   [(set_attr "type" "logics_reg")]
3608 ;; zero_extend version of above
3609 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3610   [(set (reg:CC_NZ CC_REGNUM)
3611         (compare:CC_NZ
3612          (and:SI (not:SI
3613                   (match_operand:SI 1 "register_operand" "r"))
3614                  (match_operand:SI 2 "register_operand" "r"))
3615          (const_int 0)))
3616    (set (match_operand:DI 0 "register_operand" "=r")
3617         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3618   ""
3619   "bics\\t%w0, %w2, %w1"
3620   [(set_attr "type" "logics_reg")]
3623 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3624   [(set (reg:CC_NZ CC_REGNUM)
3625     (compare:CC_NZ
3626      (and:GPI (not:GPI
3627            (match_operand:GPI 0 "register_operand" "r"))
3628           (match_operand:GPI 1 "register_operand" "r"))
3629      (const_int 0)))]
3630   ""
3631   "bics\\t<w>zr, %<w>1, %<w>0"
3632   [(set_attr "type" "logics_reg")]
3635 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3636   [(set (match_operand:GPI 0 "register_operand" "=r")
3637         (LOGICAL:GPI (not:GPI
3638                       (SHIFT:GPI
3639                        (match_operand:GPI 1 "register_operand" "r")
3640                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3641                      (match_operand:GPI 3 "register_operand" "r")))]
3642   ""
3643   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3644   [(set_attr "type" "logic_shift_imm")]
3647 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3648   [(set (match_operand:GPI 0 "register_operand" "=r")
3649         (not:GPI (xor:GPI
3650                       (SHIFT:GPI
3651                        (match_operand:GPI 1 "register_operand" "r")
3652                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3653                      (match_operand:GPI 3 "register_operand" "r"))))]
3654   ""
3655   "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3656   [(set_attr "type" "logic_shift_imm")]
3659 ;; Zero-extend version of the above.
3660 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3661   [(set (match_operand:DI 0 "register_operand" "=r")
3662         (zero_extend:DI
3663           (not:SI (xor:SI
3664                     (SHIFT:SI
3665                       (match_operand:SI 1 "register_operand" "r")
3666                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3667                     (match_operand:SI 3 "register_operand" "r")))))]
3668   ""
3669   "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3670   [(set_attr "type" "logic_shift_imm")]
3673 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3674   [(set (reg:CC_NZ CC_REGNUM)
3675         (compare:CC_NZ
3676          (and: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          (const_int 0)))
3682    (set (match_operand:GPI 0 "register_operand" "=r")
3683         (and:GPI (not:GPI
3684                   (SHIFT:GPI
3685                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
3686   ""
3687   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3688   [(set_attr "type" "logics_shift_imm")]
3691 ;; zero_extend version of above
3692 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3693   [(set (reg:CC_NZ CC_REGNUM)
3694         (compare:CC_NZ
3695          (and:SI (not:SI
3696                   (SHIFT:SI
3697                    (match_operand:SI 1 "register_operand" "r")
3698                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3699                  (match_operand:SI 3 "register_operand" "r"))
3700          (const_int 0)))
3701    (set (match_operand:DI 0 "register_operand" "=r")
3702         (zero_extend:DI (and:SI
3703                          (not:SI
3704                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3705   ""
3706   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3707   [(set_attr "type" "logics_shift_imm")]
3710 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3711   [(set (reg:CC_NZ CC_REGNUM)
3712     (compare:CC_NZ
3713      (and:GPI (not:GPI
3714            (SHIFT:GPI
3715             (match_operand:GPI 0 "register_operand" "r")
3716             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3717           (match_operand:GPI 2 "register_operand" "r"))
3718      (const_int 0)))]
3719   ""
3720   "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3721   [(set_attr "type" "logics_shift_imm")]
3724 (define_insn "clz<mode>2"
3725   [(set (match_operand:GPI 0 "register_operand" "=r")
3726         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3727   ""
3728   "clz\\t%<w>0, %<w>1"
3729   [(set_attr "type" "clz")]
3732 (define_expand "ffs<mode>2"
3733   [(match_operand:GPI 0 "register_operand")
3734    (match_operand:GPI 1 "register_operand")]
3735   ""
3736   {
3737     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3738     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3740     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3741     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3742     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3743     DONE;
3744   }
3747 (define_insn "clrsb<mode>2"
3748   [(set (match_operand:GPI 0 "register_operand" "=r")
3749         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3750   ""
3751   "cls\\t%<w>0, %<w>1"
3752   [(set_attr "type" "clz")]
3755 (define_insn "rbit<mode>2"
3756   [(set (match_operand:GPI 0 "register_operand" "=r")
3757         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3758   ""
3759   "rbit\\t%<w>0, %<w>1"
3760   [(set_attr "type" "rbit")]
3763 (define_expand "ctz<mode>2"
3764   [(match_operand:GPI 0 "register_operand")
3765    (match_operand:GPI 1 "register_operand")]
3766   ""
3767   {
3768     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3769     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3770     DONE;
3771   }
3774 (define_insn "*and<mode>_compare0"
3775   [(set (reg:CC_NZ CC_REGNUM)
3776         (compare:CC_NZ
3777          (match_operand:SHORT 0 "register_operand" "r")
3778          (const_int 0)))]
3779   ""
3780   "tst\\t%<w>0, <short_mask>"
3781   [(set_attr "type" "alus_imm")]
3784 (define_insn "*and<mode>3nr_compare0"
3785   [(set (reg:CC_NZ CC_REGNUM)
3786         (compare:CC_NZ
3787          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3788                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3789          (const_int 0)))]
3790   ""
3791   "tst\\t%<w>0, %<w>1"
3792   [(set_attr "type" "logics_reg,logics_imm")]
3795 (define_insn "*and<mode>3nr_compare0_zextract"
3796   [(set (reg:CC_NZ CC_REGNUM)
3797         (compare:CC_NZ
3798          (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3799                   (match_operand:GPI 1 "const_int_operand" "n")
3800                   (match_operand:GPI 2 "const_int_operand" "n"))
3801          (const_int 0)))]
3802   "INTVAL (operands[1]) > 0
3803    && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3804         <= GET_MODE_BITSIZE (<MODE>mode))
3805    && aarch64_bitmask_imm (
3806         UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3807                                                  operands[2])),
3808         <MODE>mode)"
3809   {
3810     operands[1]
3811       = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3812     return "tst\\t%<w>0, %1";
3813   }
3814   [(set_attr "type" "logics_shift_imm")]
3817 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3818   [(set (reg:CC_NZ CC_REGNUM)
3819         (compare:CC_NZ
3820          (and:GPI (SHIFT:GPI
3821                    (match_operand:GPI 0 "register_operand" "r")
3822                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3823                   (match_operand:GPI 2 "register_operand" "r"))
3824         (const_int 0)))]
3825   ""
3826   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3827   [(set_attr "type" "logics_shift_imm")]
3830 ;; -------------------------------------------------------------------
3831 ;; Shifts
3832 ;; -------------------------------------------------------------------
3834 (define_expand "<optab><mode>3"
3835   [(set (match_operand:GPI 0 "register_operand")
3836         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3837                     (match_operand:QI 2 "nonmemory_operand")))]
3838   ""
3839   {
3840     if (CONST_INT_P (operands[2]))
3841       {
3842         operands[2] = GEN_INT (INTVAL (operands[2])
3843                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3845         if (operands[2] == const0_rtx)
3846           {
3847             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3848             DONE;
3849           }
3850       }
3851   }
3854 (define_expand "ashl<mode>3"
3855   [(set (match_operand:SHORT 0 "register_operand")
3856         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3857                       (match_operand:QI 2 "nonmemory_operand")))]
3858   ""
3859   {
3860     if (CONST_INT_P (operands[2]))
3861       {
3862         operands[2] = GEN_INT (INTVAL (operands[2])
3863                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3865         if (operands[2] == const0_rtx)
3866           {
3867             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3868             DONE;
3869           }
3870       }
3871     else
3872       FAIL;
3873   }
3876 (define_expand "rotr<mode>3"
3877   [(set (match_operand:GPI 0 "register_operand")
3878         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3879                       (match_operand:QI 2 "nonmemory_operand")))]
3880   ""
3881   {
3882     if (CONST_INT_P (operands[2]))
3883       {
3884         operands[2] = GEN_INT (INTVAL (operands[2])
3885                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3887         if (operands[2] == const0_rtx)
3888           {
3889             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3890             DONE;
3891           }
3892       }
3893   }
3896 (define_expand "rotl<mode>3"
3897   [(set (match_operand:GPI 0 "register_operand")
3898         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3899                       (match_operand:QI 2 "nonmemory_operand")))]
3900   ""
3901   {
3902     /* (SZ - cnt) % SZ == -cnt % SZ */
3903     if (CONST_INT_P (operands[2]))
3904       {
3905         operands[2] = GEN_INT ((-INTVAL (operands[2]))
3906                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3907         if (operands[2] == const0_rtx)
3908           {
3909             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3910             DONE;
3911           }
3912       }
3913     else
3914       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3915                                         NULL_RTX, 1);
3916   }
3919 ;; Logical left shift using SISD or Integer instruction
3920 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3921   [(set (match_operand:GPI 0 "register_operand" "=r,w,w")
3922         (ashift:GPI
3923           (match_operand:GPI 1 "register_operand" "r,w,w")
3924           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "rUs<cmode>,Us<cmode>,w")))]
3925   ""
3926   "@
3927    lsl\t%<w>0, %<w>1, %<w>2
3928    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3929    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3930   [(set_attr "simd" "no,yes,yes")
3931    (set_attr "type" "shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3934 ;; Logical right shift using SISD or Integer instruction
3935 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3936   [(set (match_operand:GPI 0 "register_operand" "=r,w,&w,&w")
3937         (lshiftrt:GPI
3938           (match_operand:GPI 1 "register_operand" "r,w,w,w")
3939           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "rUs<cmode>,Us<cmode>,w,0")))]
3940   ""
3941   "@
3942    lsr\t%<w>0, %<w>1, %<w>2
3943    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3944    #
3945    #"
3946   [(set_attr "simd" "no,yes,yes,yes")
3947    (set_attr "type" "shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
3950 (define_split
3951   [(set (match_operand:DI 0 "aarch64_simd_register")
3952         (lshiftrt:DI
3953            (match_operand:DI 1 "aarch64_simd_register")
3954            (match_operand:QI 2 "aarch64_simd_register")))]
3955   "TARGET_SIMD && reload_completed"
3956   [(set (match_dup 3)
3957         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3958    (set (match_dup 0)
3959         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
3960   {
3961     operands[3] = gen_lowpart (QImode, operands[0]);
3962   }
3965 (define_split
3966   [(set (match_operand:SI 0 "aarch64_simd_register")
3967         (lshiftrt:SI
3968            (match_operand:SI 1 "aarch64_simd_register")
3969            (match_operand:QI 2 "aarch64_simd_register")))]
3970   "TARGET_SIMD && reload_completed"
3971   [(set (match_dup 3)
3972         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3973    (set (match_dup 0)
3974         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
3975   {
3976     operands[3] = gen_lowpart (QImode, operands[0]);
3977   }
3980 ;; Arithmetic right shift using SISD or Integer instruction
3981 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
3982   [(set (match_operand:GPI 0 "register_operand" "=r,w,&w,&w")
3983         (ashiftrt:GPI
3984           (match_operand:GPI 1 "register_operand" "r,w,w,w")
3985           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "rUs<cmode>,Us<cmode>,w,0")))]
3986   ""
3987   "@
3988    asr\t%<w>0, %<w>1, %<w>2
3989    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3990    #
3991    #"
3992   [(set_attr "simd" "no,yes,yes,yes")
3993    (set_attr "type" "shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
3996 (define_split
3997   [(set (match_operand:DI 0 "aarch64_simd_register")
3998         (ashiftrt:DI
3999            (match_operand:DI 1 "aarch64_simd_register")
4000            (match_operand:QI 2 "aarch64_simd_register")))]
4001   "TARGET_SIMD && reload_completed"
4002   [(set (match_dup 3)
4003         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4004    (set (match_dup 0)
4005         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4007   operands[3] = gen_lowpart (QImode, operands[0]);
4011 (define_split
4012   [(set (match_operand:SI 0 "aarch64_simd_register")
4013         (ashiftrt:SI
4014            (match_operand:SI 1 "aarch64_simd_register")
4015            (match_operand:QI 2 "aarch64_simd_register")))]
4016   "TARGET_SIMD && reload_completed"
4017   [(set (match_dup 3)
4018         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4019    (set (match_dup 0)
4020         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4022   operands[3] = gen_lowpart (QImode, operands[0]);
4026 (define_insn "*aarch64_sisd_ushl"
4027   [(set (match_operand:DI 0 "register_operand" "=w")
4028         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4029                     (match_operand:QI 2 "register_operand" "w")]
4030                    UNSPEC_SISD_USHL))]
4031   "TARGET_SIMD"
4032   "ushl\t%d0, %d1, %d2"
4033   [(set_attr "simd" "yes")
4034    (set_attr "type" "neon_shift_reg")]
4037 (define_insn "*aarch64_ushl_2s"
4038   [(set (match_operand:SI 0 "register_operand" "=w")
4039         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4040                     (match_operand:QI 2 "register_operand" "w")]
4041                    UNSPEC_USHL_2S))]
4042   "TARGET_SIMD"
4043   "ushl\t%0.2s, %1.2s, %2.2s"
4044   [(set_attr "simd" "yes")
4045    (set_attr "type" "neon_shift_reg")]
4048 (define_insn "*aarch64_sisd_sshl"
4049   [(set (match_operand:DI 0 "register_operand" "=w")
4050         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4051                     (match_operand:QI 2 "register_operand" "w")]
4052                    UNSPEC_SISD_SSHL))]
4053   "TARGET_SIMD"
4054   "sshl\t%d0, %d1, %d2"
4055   [(set_attr "simd" "yes")
4056    (set_attr "type" "neon_shift_reg")]
4059 (define_insn "*aarch64_sshl_2s"
4060   [(set (match_operand:SI 0 "register_operand" "=w")
4061         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4062                     (match_operand:QI 2 "register_operand" "w")]
4063                    UNSPEC_SSHL_2S))]
4064   "TARGET_SIMD"
4065   "sshl\t%0.2s, %1.2s, %2.2s"
4066   [(set_attr "simd" "yes")
4067    (set_attr "type" "neon_shift_reg")]
4070 (define_insn "*aarch64_sisd_neg_qi"
4071   [(set (match_operand:QI 0 "register_operand" "=w")
4072         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4073                    UNSPEC_SISD_NEG))]
4074   "TARGET_SIMD"
4075   "neg\t%d0, %d1"
4076   [(set_attr "simd" "yes")
4077    (set_attr "type" "neon_neg")]
4080 ;; Rotate right
4081 (define_insn "*ror<mode>3_insn"
4082   [(set (match_operand:GPI 0 "register_operand" "=r,r")
4083      (rotatert:GPI
4084        (match_operand:GPI 1 "register_operand" "r,r")
4085        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "r,Us<cmode>")))]
4086   ""
4087   "ror\\t%<w>0, %<w>1, %<w>2"
4088   [(set_attr "type" "shift_reg, rotate_imm")]
4091 ;; zero_extend version of above
4092 (define_insn "*<optab>si3_insn_uxtw"
4093   [(set (match_operand:DI 0 "register_operand" "=r")
4094         (zero_extend:DI (SHIFT:SI
4095          (match_operand:SI 1 "register_operand" "r")
4096          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "rUss"))))]
4097   ""
4098   "<shift>\\t%w0, %w1, %w2"
4099   [(set_attr "type" "shift_reg")]
4102 (define_insn "*<optab><mode>3_insn"
4103   [(set (match_operand:SHORT 0 "register_operand" "=r")
4104         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4105                       (match_operand 2 "const_int_operand" "n")))]
4106   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4108   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4109   return "<bfshift>\t%w0, %w1, %2, %3";
4111   [(set_attr "type" "bfm")]
4114 (define_insn "*extr<mode>5_insn"
4115   [(set (match_operand:GPI 0 "register_operand" "=r")
4116         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4117                              (match_operand 3 "const_int_operand" "n"))
4118                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4119                                (match_operand 4 "const_int_operand" "n"))))]
4120   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4121    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4122   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4123   [(set_attr "type" "shift_imm")]
4126 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4127 ;; so we have to match both orderings.
4128 (define_insn "*extr<mode>5_insn_alt"
4129   [(set (match_operand:GPI 0 "register_operand" "=r")
4130         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4131                                 (match_operand 4 "const_int_operand" "n"))
4132                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4133                               (match_operand 3 "const_int_operand" "n"))))]
4134   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4135    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4136        == GET_MODE_BITSIZE (<MODE>mode))"
4137   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4138   [(set_attr "type" "shift_imm")]
4141 ;; zero_extend version of the above
4142 (define_insn "*extrsi5_insn_uxtw"
4143   [(set (match_operand:DI 0 "register_operand" "=r")
4144         (zero_extend:DI
4145          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4146                             (match_operand 3 "const_int_operand" "n"))
4147                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4148                               (match_operand 4 "const_int_operand" "n")))))]
4149   "UINTVAL (operands[3]) < 32 &&
4150    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4151   "extr\\t%w0, %w1, %w2, %4"
4152   [(set_attr "type" "shift_imm")]
4155 (define_insn "*extrsi5_insn_uxtw_alt"
4156   [(set (match_operand:DI 0 "register_operand" "=r")
4157         (zero_extend:DI
4158          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4159                                (match_operand 4 "const_int_operand" "n"))
4160                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
4161                             (match_operand 3 "const_int_operand" "n")))))]
4162   "UINTVAL (operands[3]) < 32 &&
4163    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4164   "extr\\t%w0, %w1, %w2, %4"
4165   [(set_attr "type" "shift_imm")]
4168 (define_insn "*ror<mode>3_insn"
4169   [(set (match_operand:GPI 0 "register_operand" "=r")
4170         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4171                     (match_operand 2 "const_int_operand" "n")))]
4172   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4174   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4175   return "ror\\t%<w>0, %<w>1, %3";
4177   [(set_attr "type" "rotate_imm")]
4180 ;; zero_extend version of the above
4181 (define_insn "*rorsi3_insn_uxtw"
4182   [(set (match_operand:DI 0 "register_operand" "=r")
4183         (zero_extend:DI
4184          (rotate:SI (match_operand:SI 1 "register_operand" "r")
4185                     (match_operand 2 "const_int_operand" "n"))))]
4186   "UINTVAL (operands[2]) < 32"
4188   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4189   return "ror\\t%w0, %w1, %3";
4191   [(set_attr "type" "rotate_imm")]
4194 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4195   [(set (match_operand:GPI 0 "register_operand" "=r")
4196         (ANY_EXTEND:GPI
4197          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4198                        (match_operand 2 "const_int_operand" "n"))))]
4199   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4201   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4202   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4204   [(set_attr "type" "bfm")]
4207 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4208   [(set (match_operand:GPI 0 "register_operand" "=r")
4209         (zero_extend:GPI
4210          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4211                          (match_operand 2 "const_int_operand" "n"))))]
4212   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4214   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4215   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4217   [(set_attr "type" "bfm")]
4220 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4221   [(set (match_operand:GPI 0 "register_operand" "=r")
4222         (sign_extend:GPI
4223          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4224                          (match_operand 2 "const_int_operand" "n"))))]
4225   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4227   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4228   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4230   [(set_attr "type" "bfm")]
4233 ;; -------------------------------------------------------------------
4234 ;; Bitfields
4235 ;; -------------------------------------------------------------------
4237 (define_expand "<optab>"
4238   [(set (match_operand:DI 0 "register_operand" "=r")
4239         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand" "r")
4240                         (match_operand 2 "const_int_operand" "n")
4241                         (match_operand 3 "const_int_operand" "n")))]
4242   ""
4243   ""
4246 (define_insn "*<optab><mode>"
4247   [(set (match_operand:GPI 0 "register_operand" "=r")
4248         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4249                          (match_operand 2 "const_int_operand" "n")
4250                          (match_operand 3 "const_int_operand" "n")))]
4251   ""
4252   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4253   [(set_attr "type" "bfm")]
4256 ;; Bitfield Insert (insv)
4257 (define_expand "insv<mode>"
4258   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4259                           (match_operand 1 "const_int_operand")
4260                           (match_operand 2 "const_int_operand"))
4261         (match_operand:GPI 3 "general_operand"))]
4262   ""
4264   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4265   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4266   rtx value = operands[3];
4268   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4269     FAIL;
4271   if (CONST_INT_P (value))
4272     {
4273       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4275       /* Prefer AND/OR for inserting all zeros or all ones.  */
4276       if ((UINTVAL (value) & mask) == 0
4277            || (UINTVAL (value) & mask) == mask)
4278         FAIL;
4280       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
4281       if (width == 16 && (pos % 16) == 0)
4282         DONE;
4283     }
4284   operands[3] = force_reg (<MODE>mode, value);
4287 (define_insn "*insv_reg<mode>"
4288   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4289                           (match_operand 1 "const_int_operand" "n")
4290                           (match_operand 2 "const_int_operand" "n"))
4291         (match_operand:GPI 3 "register_operand" "r"))]
4292   "!(UINTVAL (operands[1]) == 0
4293      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4294          > GET_MODE_BITSIZE (<MODE>mode)))"
4295   "bfi\\t%<w>0, %<w>3, %2, %1"
4296   [(set_attr "type" "bfm")]
4299 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4300   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4301                           (match_operand 1 "const_int_operand" "n")
4302                           (match_operand 2 "const_int_operand" "n"))
4303         (zero_extend:GPI (match_operand:ALLX 3  "register_operand" "r")))]
4304   "UINTVAL (operands[1]) <= <ALLX:sizen>"
4305   "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4306   [(set_attr "type" "bfm")]
4309 (define_insn "*extr_insv_lower_reg<mode>"
4310   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4311                           (match_operand 1 "const_int_operand" "n")
4312                           (const_int 0))
4313         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4314                           (match_dup 1)
4315                           (match_operand 3 "const_int_operand" "n")))]
4316   "!(UINTVAL (operands[1]) == 0
4317      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4318          > GET_MODE_BITSIZE (<MODE>mode)))"
4319   "bfxil\\t%<w>0, %<w>2, %3, %1"
4320   [(set_attr "type" "bfm")]
4323 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4324   [(set (match_operand:GPI 0 "register_operand" "=r")
4325         (ashift:GPI (ANY_EXTEND:GPI
4326                      (match_operand:ALLX 1 "register_operand" "r"))
4327                     (match_operand 2 "const_int_operand" "n")))]
4328   "UINTVAL (operands[2]) < <GPI:sizen>"
4330   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4331               ? GEN_INT (<ALLX:sizen>)
4332               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4333   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4335   [(set_attr "type" "bfm")]
4338 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4340 (define_insn "*andim_ashift<mode>_bfiz"
4341   [(set (match_operand:GPI 0 "register_operand" "=r")
4342         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4343                              (match_operand 2 "const_int_operand" "n"))
4344                  (match_operand 3 "const_int_operand" "n")))]
4345   "(INTVAL (operands[2]) < (<GPI:sizen>))
4346    && exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1) >= 0
4347    && (INTVAL (operands[3]) & ((1 << INTVAL (operands[2])) - 1)) == 0"
4348   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4349   [(set_attr "type" "bfm")]
4352 (define_insn "bswap<mode>2"
4353   [(set (match_operand:GPI 0 "register_operand" "=r")
4354         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4355   ""
4356   "rev\\t%<w>0, %<w>1"
4357   [(set_attr "type" "rev")]
4360 (define_insn "bswaphi2"
4361   [(set (match_operand:HI 0 "register_operand" "=r")
4362         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4363   ""
4364   "rev16\\t%w0, %w1"
4365   [(set_attr "type" "rev")]
4368 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4369 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4370 ;; each valid permutation.
4372 (define_insn "rev16<mode>2"
4373   [(set (match_operand:GPI 0 "register_operand" "=r")
4374         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4375                                       (const_int 8))
4376                           (match_operand:GPI 3 "const_int_operand" "n"))
4377                  (and:GPI (lshiftrt:GPI (match_dup 1)
4378                                         (const_int 8))
4379                           (match_operand:GPI 2 "const_int_operand" "n"))))]
4380   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4381    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4382   "rev16\\t%<w>0, %<w>1"
4383   [(set_attr "type" "rev")]
4386 (define_insn "rev16<mode>2_alt"
4387   [(set (match_operand:GPI 0 "register_operand" "=r")
4388         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4389                                         (const_int 8))
4390                           (match_operand:GPI 2 "const_int_operand" "n"))
4391                  (and:GPI (ashift:GPI (match_dup 1)
4392                                       (const_int 8))
4393                           (match_operand:GPI 3 "const_int_operand" "n"))))]
4394   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4395    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4396   "rev16\\t%<w>0, %<w>1"
4397   [(set_attr "type" "rev")]
4400 ;; zero_extend version of above
4401 (define_insn "*bswapsi2_uxtw"
4402   [(set (match_operand:DI 0 "register_operand" "=r")
4403         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4404   ""
4405   "rev\\t%w0, %w1"
4406   [(set_attr "type" "rev")]
4409 ;; -------------------------------------------------------------------
4410 ;; Floating-point intrinsics
4411 ;; -------------------------------------------------------------------
4413 ;; frint floating-point round to integral standard patterns.
4414 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4416 (define_insn "<frint_pattern><mode>2"
4417   [(set (match_operand:GPF 0 "register_operand" "=w")
4418         (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
4419          FRINT))]
4420   "TARGET_FLOAT"
4421   "frint<frint_suffix>\\t%<s>0, %<s>1"
4422   [(set_attr "type" "f_rint<s>")]
4425 ;; frcvt floating-point round to integer and convert standard patterns.
4426 ;; Expands to lbtrunc, lceil, lfloor, lround.
4427 (define_insn "l<fcvt_pattern><su_optab><GPF:mode><GPI:mode>2"
4428   [(set (match_operand:GPI 0 "register_operand" "=r")
4429         (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
4430                       FCVT)))]
4431   "TARGET_FLOAT"
4432   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF:s>1"
4433   [(set_attr "type" "f_cvtf2i")]
4436 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4437   [(set (match_operand:GPI 0 "register_operand" "=r")
4438         (FIXUORS:GPI
4439           (mult:GPF
4440             (match_operand:GPF 1 "register_operand" "w")
4441             (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4442   "TARGET_FLOAT
4443    && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4444                 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4445   {
4446     int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4447     char buf[64];
4448     snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4449     output_asm_insn (buf, operands);
4450     return "";
4451   }
4452   [(set_attr "type" "f_cvtf2i")]
4455 ;; fma - no throw
4457 (define_insn "fma<mode>4"
4458   [(set (match_operand:GPF 0 "register_operand" "=w")
4459         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4460                  (match_operand:GPF 2 "register_operand" "w")
4461                  (match_operand:GPF 3 "register_operand" "w")))]
4462   "TARGET_FLOAT"
4463   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4464   [(set_attr "type" "fmac<s>")]
4467 (define_insn "fnma<mode>4"
4468   [(set (match_operand:GPF 0 "register_operand" "=w")
4469         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4470                  (match_operand:GPF 2 "register_operand" "w")
4471                  (match_operand:GPF 3 "register_operand" "w")))]
4472   "TARGET_FLOAT"
4473   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4474   [(set_attr "type" "fmac<s>")]
4477 (define_insn "fms<mode>4"
4478   [(set (match_operand:GPF 0 "register_operand" "=w")
4479         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4480                  (match_operand:GPF 2 "register_operand" "w")
4481                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4482   "TARGET_FLOAT"
4483   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4484   [(set_attr "type" "fmac<s>")]
4487 (define_insn "fnms<mode>4"
4488   [(set (match_operand:GPF 0 "register_operand" "=w")
4489         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4490                  (match_operand:GPF 2 "register_operand" "w")
4491                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4492   "TARGET_FLOAT"
4493   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4494   [(set_attr "type" "fmac<s>")]
4497 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4498 (define_insn "*fnmadd<mode>4"
4499   [(set (match_operand:GPF 0 "register_operand" "=w")
4500         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4501                           (match_operand:GPF 2 "register_operand" "w")
4502                           (match_operand:GPF 3 "register_operand" "w"))))]
4503   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4504   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4505   [(set_attr "type" "fmac<s>")]
4508 ;; -------------------------------------------------------------------
4509 ;; Floating-point conversions
4510 ;; -------------------------------------------------------------------
4512 (define_insn "extendsfdf2"
4513   [(set (match_operand:DF 0 "register_operand" "=w")
4514         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4515   "TARGET_FLOAT"
4516   "fcvt\\t%d0, %s1"
4517   [(set_attr "type" "f_cvt")]
4520 (define_insn "extendhfsf2"
4521   [(set (match_operand:SF 0 "register_operand" "=w")
4522         (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4523   "TARGET_FLOAT"
4524   "fcvt\\t%s0, %h1"
4525   [(set_attr "type" "f_cvt")]
4528 (define_insn "extendhfdf2"
4529   [(set (match_operand:DF 0 "register_operand" "=w")
4530         (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4531   "TARGET_FLOAT"
4532   "fcvt\\t%d0, %h1"
4533   [(set_attr "type" "f_cvt")]
4536 (define_insn "truncdfsf2"
4537   [(set (match_operand:SF 0 "register_operand" "=w")
4538         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4539   "TARGET_FLOAT"
4540   "fcvt\\t%s0, %d1"
4541   [(set_attr "type" "f_cvt")]
4544 (define_insn "truncsfhf2"
4545   [(set (match_operand:HF 0 "register_operand" "=w")
4546         (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4547   "TARGET_FLOAT"
4548   "fcvt\\t%h0, %s1"
4549   [(set_attr "type" "f_cvt")]
4552 (define_insn "truncdfhf2"
4553   [(set (match_operand:HF 0 "register_operand" "=w")
4554         (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4555   "TARGET_FLOAT"
4556   "fcvt\\t%h0, %d1"
4557   [(set_attr "type" "f_cvt")]
4560 (define_insn "fix_trunc<GPF:mode><GPI:mode>2"
4561   [(set (match_operand:GPI 0 "register_operand" "=r")
4562         (fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
4563   "TARGET_FLOAT"
4564   "fcvtzs\\t%<GPI:w>0, %<GPF:s>1"
4565   [(set_attr "type" "f_cvtf2i")]
4568 (define_insn "fixuns_trunc<GPF:mode><GPI:mode>2"
4569   [(set (match_operand:GPI 0 "register_operand" "=r")
4570         (unsigned_fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
4571   "TARGET_FLOAT"
4572   "fcvtzu\\t%<GPI:w>0, %<GPF:s>1"
4573   [(set_attr "type" "f_cvtf2i")]
4576 (define_insn "<optab><fcvt_target><GPF:mode>2"
4577   [(set (match_operand:GPF 0 "register_operand" "=w,w")
4578         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4579   "TARGET_FLOAT"
4580   "@
4581    <su_optab>cvtf\t%<GPF:s>0, %<s>1
4582    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4583   [(set_attr "simd" "yes,no")
4584    (set_attr "fp" "no,yes")
4585    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4588 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4589   [(set (match_operand:GPF 0 "register_operand" "=w")
4590         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4591   "TARGET_FLOAT"
4592   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4593   [(set_attr "type" "f_cvti2f")]
4596 ;; -------------------------------------------------------------------
4597 ;; Floating-point arithmetic
4598 ;; -------------------------------------------------------------------
4600 (define_insn "add<mode>3"
4601   [(set (match_operand:GPF 0 "register_operand" "=w")
4602         (plus:GPF
4603          (match_operand:GPF 1 "register_operand" "w")
4604          (match_operand:GPF 2 "register_operand" "w")))]
4605   "TARGET_FLOAT"
4606   "fadd\\t%<s>0, %<s>1, %<s>2"
4607   [(set_attr "type" "fadd<s>")]
4610 (define_insn "sub<mode>3"
4611   [(set (match_operand:GPF 0 "register_operand" "=w")
4612         (minus:GPF
4613          (match_operand:GPF 1 "register_operand" "w")
4614          (match_operand:GPF 2 "register_operand" "w")))]
4615   "TARGET_FLOAT"
4616   "fsub\\t%<s>0, %<s>1, %<s>2"
4617   [(set_attr "type" "fadd<s>")]
4620 (define_insn "mul<mode>3"
4621   [(set (match_operand:GPF 0 "register_operand" "=w")
4622         (mult:GPF
4623          (match_operand:GPF 1 "register_operand" "w")
4624          (match_operand:GPF 2 "register_operand" "w")))]
4625   "TARGET_FLOAT"
4626   "fmul\\t%<s>0, %<s>1, %<s>2"
4627   [(set_attr "type" "fmul<s>")]
4630 (define_insn "*fnmul<mode>3"
4631   [(set (match_operand:GPF 0 "register_operand" "=w")
4632         (mult:GPF
4633                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4634                  (match_operand:GPF 2 "register_operand" "w")))]
4635   "TARGET_FLOAT && !flag_rounding_math"
4636   "fnmul\\t%<s>0, %<s>1, %<s>2"
4637   [(set_attr "type" "fmul<s>")]
4640 (define_insn "*fnmul<mode>3"
4641   [(set (match_operand:GPF 0 "register_operand" "=w")
4642         (neg:GPF (mult:GPF
4643                  (match_operand:GPF 1 "register_operand" "w")
4644                  (match_operand:GPF 2 "register_operand" "w"))))]
4645   "TARGET_FLOAT"
4646   "fnmul\\t%<s>0, %<s>1, %<s>2"
4647   [(set_attr "type" "fmul<s>")]
4650 (define_insn "div<mode>3"
4651   [(set (match_operand:GPF 0 "register_operand" "=w")
4652         (div:GPF
4653          (match_operand:GPF 1 "register_operand" "w")
4654          (match_operand:GPF 2 "register_operand" "w")))]
4655   "TARGET_FLOAT"
4656   "fdiv\\t%<s>0, %<s>1, %<s>2"
4657   [(set_attr "type" "fdiv<s>")]
4660 (define_insn "neg<mode>2"
4661   [(set (match_operand:GPF 0 "register_operand" "=w")
4662         (neg:GPF (match_operand:GPF 1 "register_operand" "w")))]
4663   "TARGET_FLOAT"
4664   "fneg\\t%<s>0, %<s>1"
4665   [(set_attr "type" "ffarith<s>")]
4668 (define_insn "sqrt<mode>2"
4669   [(set (match_operand:GPF 0 "register_operand" "=w")
4670         (sqrt:GPF (match_operand:GPF 1 "register_operand" "w")))]
4671   "TARGET_FLOAT"
4672   "fsqrt\\t%<s>0, %<s>1"
4673   [(set_attr "type" "fsqrt<s>")]
4676 (define_insn "abs<mode>2"
4677   [(set (match_operand:GPF 0 "register_operand" "=w")
4678         (abs:GPF (match_operand:GPF 1 "register_operand" "w")))]
4679   "TARGET_FLOAT"
4680   "fabs\\t%<s>0, %<s>1"
4681   [(set_attr "type" "ffarith<s>")]
4684 ;; Given that smax/smin do not specify the result when either input is NaN,
4685 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4686 ;; for smin.
4688 (define_insn "smax<mode>3"
4689   [(set (match_operand:GPF 0 "register_operand" "=w")
4690         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4691                   (match_operand:GPF 2 "register_operand" "w")))]
4692   "TARGET_FLOAT"
4693   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4694   [(set_attr "type" "f_minmax<s>")]
4697 (define_insn "smin<mode>3"
4698   [(set (match_operand:GPF 0 "register_operand" "=w")
4699         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4700                   (match_operand:GPF 2 "register_operand" "w")))]
4701   "TARGET_FLOAT"
4702   "fminnm\\t%<s>0, %<s>1, %<s>2"
4703   [(set_attr "type" "f_minmax<s>")]
4706 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
4707 (define_insn "<fmaxmin><mode>3"
4708   [(set (match_operand:GPF 0 "register_operand" "=w")
4709         (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")
4710                      (match_operand:GPF 2 "register_operand" "w")]
4711                      FMAXMIN))]
4712   "TARGET_FLOAT"
4713   "<fmaxmin_op>\\t%<s>0, %<s>1, %<s>2"
4714   [(set_attr "type" "f_minmax<s>")]
4717 ;; For copysign (x, y), we want to generate:
4719 ;;   LDR d2, #(1 << 63)
4720 ;;   BSL v2.8b, [y], [x]
4722 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4723 ;; aarch64_simd_bsldf will select the best suited of these instructions
4724 ;; to generate based on register allocation, and knows how to partially
4725 ;; constant fold based on the values of X and Y, so expand through that.
4727 (define_expand "copysigndf3"
4728   [(match_operand:DF 0 "register_operand")
4729    (match_operand:DF 1 "register_operand")
4730    (match_operand:DF 2 "register_operand")]
4731   "TARGET_FLOAT && TARGET_SIMD"
4733   rtx mask = gen_reg_rtx (DImode);
4734   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4735   emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4736                                      operands[2], operands[1]));
4737   DONE;
4741 ;; As above, but we must first get to a 64-bit value if we wish to use
4742 ;; aarch64_simd_bslv2sf.
4744 (define_expand "copysignsf3"
4745   [(match_operand:SF 0 "register_operand")
4746    (match_operand:SF 1 "register_operand")
4747    (match_operand:SF 2 "register_operand")]
4748   "TARGET_FLOAT && TARGET_SIMD"
4750   rtx mask = gen_reg_rtx (DImode);
4752   /* Juggle modes to get us in to a vector mode for BSL.  */
4753   rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4754   rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4755   rtx tmp = gen_reg_rtx (V2SFmode);
4756   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4757   emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4758   emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
4759   DONE;
4763 ;; -------------------------------------------------------------------
4764 ;; Reload support
4765 ;; -------------------------------------------------------------------
4766 ;; Reload Scalar Floating point modes from constant pool.
4767 ;; The AArch64 port doesn't have __int128 constant move support.
4768 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
4769  [(set (match_operand:GPF_TF 0 "register_operand" "=w")
4770        (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
4771   (clobber (match_operand:P 2 "register_operand" "=&r"))]
4772  "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
4774    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
4775    emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
4776    DONE;
4780 ;; Reload Vector modes from constant pool.
4781 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
4782  [(set (match_operand:VALL 0 "register_operand" "=w")
4783        (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
4784   (clobber (match_operand:P 2 "register_operand" "=&r"))]
4785  "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
4787    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
4788    emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
4789    DONE;
4793 (define_expand "aarch64_reload_mov<mode>"
4794   [(set (match_operand:TX 0 "register_operand" "=w")
4795         (match_operand:TX 1 "register_operand" "w"))
4796    (clobber (match_operand:DI 2 "register_operand" "=&r"))
4797   ]
4798   "TARGET_FLOAT"
4799   {
4800     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
4801     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
4802     gen_aarch64_movtilow_tilow (op0, op1);
4803     gen_aarch64_movdi_tihigh (operands[2], op1);
4804     gen_aarch64_movtihigh_di (op0, operands[2]);
4805     DONE;
4806   }
4809 ;; The following secondary reload helpers patterns are invoked
4810 ;; after or during reload as we don't want these patterns to start
4811 ;; kicking in during the combiner.
4813 (define_insn "aarch64_movdi_<mode>low"
4814   [(set (match_operand:DI 0 "register_operand" "=r")
4815         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
4816                          (const_int 64) (const_int 0)))]
4817   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4818   "fmov\\t%x0, %d1"
4819   [(set_attr "type" "f_mrc")
4820    (set_attr "length" "4")
4821   ])
4823 (define_insn "aarch64_movdi_<mode>high"
4824   [(set (match_operand:DI 0 "register_operand" "=r")
4825         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
4826                          (const_int 64) (const_int 64)))]
4827   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4828   "fmov\\t%x0, %1.d[1]"
4829   [(set_attr "type" "f_mrc")
4830    (set_attr "length" "4")
4831   ])
4833 (define_insn "aarch64_mov<mode>high_di"
4834   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
4835                          (const_int 64) (const_int 64))
4836         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
4837   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4838   "fmov\\t%0.d[1], %x1"
4839   [(set_attr "type" "f_mcr")
4840    (set_attr "length" "4")
4841   ])
4843 (define_insn "aarch64_mov<mode>low_di"
4844   [(set (match_operand:TX 0 "register_operand" "=w")
4845         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
4846   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4847   "fmov\\t%d0, %x1"
4848   [(set_attr "type" "f_mcr")
4849    (set_attr "length" "4")
4850   ])
4852 (define_insn "aarch64_movtilow_tilow"
4853   [(set (match_operand:TI 0 "register_operand" "=w")
4854         (zero_extend:TI
4855           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
4856   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4857   "fmov\\t%d0, %d1"
4858   [(set_attr "type" "fmov")
4859    (set_attr "length" "4")
4860   ])
4862 ;; There is a deliberate reason why the parameters of high and lo_sum's
4863 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
4864 ;; and lo_sum's to be used with the labels defining the jump tables in
4865 ;; rodata section.
4867 (define_expand "add_losym"
4868   [(set (match_operand 0 "register_operand" "=r")
4869         (lo_sum (match_operand 1 "register_operand" "r")
4870                 (match_operand 2 "aarch64_valid_symref" "S")))]
4871   ""
4873   machine_mode mode = GET_MODE (operands[0]);
4875   emit_insn ((mode == DImode
4876               ? gen_add_losym_di
4877               : gen_add_losym_si) (operands[0],
4878                                    operands[1],
4879                                    operands[2]));
4880   DONE;
4883 (define_insn "add_losym_<mode>"
4884   [(set (match_operand:P 0 "register_operand" "=r")
4885         (lo_sum:P (match_operand:P 1 "register_operand" "r")
4886                   (match_operand 2 "aarch64_valid_symref" "S")))]
4887   ""
4888   "add\\t%<w>0, %<w>1, :lo12:%a2"
4889   [(set_attr "type" "alu_imm")]
4892 (define_insn "ldr_got_small_<mode>"
4893   [(set (match_operand:PTR 0 "register_operand" "=r")
4894         (unspec:PTR [(mem:PTR (lo_sum:PTR
4895                               (match_operand:PTR 1 "register_operand" "r")
4896                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
4897                     UNSPEC_GOTSMALLPIC))]
4898   ""
4899   "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
4900   [(set_attr "type" "load1")]
4903 (define_insn "ldr_got_small_sidi"
4904   [(set (match_operand:DI 0 "register_operand" "=r")
4905         (zero_extend:DI
4906          (unspec:SI [(mem:SI (lo_sum:DI
4907                              (match_operand:DI 1 "register_operand" "r")
4908                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
4909                     UNSPEC_GOTSMALLPIC)))]
4910   "TARGET_ILP32"
4911   "ldr\\t%w0, [%1, #:got_lo12:%a2]"
4912   [(set_attr "type" "load1")]
4915 (define_insn "ldr_got_small_28k_<mode>"
4916   [(set (match_operand:PTR 0 "register_operand" "=r")
4917         (unspec:PTR [(mem:PTR (lo_sum:PTR
4918                               (match_operand:PTR 1 "register_operand" "r")
4919                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
4920                     UNSPEC_GOTSMALLPIC28K))]
4921   ""
4922   "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
4923   [(set_attr "type" "load1")]
4926 (define_insn "ldr_got_small_28k_sidi"
4927   [(set (match_operand:DI 0 "register_operand" "=r")
4928         (zero_extend:DI
4929          (unspec:SI [(mem:SI (lo_sum:DI
4930                              (match_operand:DI 1 "register_operand" "r")
4931                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
4932                     UNSPEC_GOTSMALLPIC28K)))]
4933   "TARGET_ILP32"
4934   "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
4935   [(set_attr "type" "load1")]
4938 (define_insn "ldr_got_tiny"
4939   [(set (match_operand:DI 0 "register_operand" "=r")
4940         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
4941                    UNSPEC_GOTTINYPIC))]
4942   ""
4943   "ldr\\t%0, %L1"
4944   [(set_attr "type" "load1")]
4947 (define_insn "aarch64_load_tp_hard"
4948   [(set (match_operand:DI 0 "register_operand" "=r")
4949         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
4950   ""
4951   "mrs\\t%0, tpidr_el0"
4952   [(set_attr "type" "mrs")]
4955 ;; The TLS ABI specifically requires that the compiler does not schedule
4956 ;; instructions in the TLS stubs, in order to enable linker relaxation.
4957 ;; Therefore we treat the stubs as an atomic sequence.
4958 (define_expand "tlsgd_small"
4959  [(parallel [(set (match_operand 0 "register_operand" "")
4960                   (call (mem:DI (match_dup 2)) (const_int 1)))
4961              (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
4962              (clobber (reg:DI LR_REGNUM))])]
4963  ""
4965   operands[2] = aarch64_tls_get_addr ();
4968 (define_insn "*tlsgd_small"
4969   [(set (match_operand 0 "register_operand" "")
4970         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
4971    (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
4972    (clobber (reg:DI LR_REGNUM))
4973   ]
4974   ""
4975   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
4976   [(set_attr "type" "call")
4977    (set_attr "length" "16")])
4979 (define_insn "tlsie_small_<mode>"
4980   [(set (match_operand:PTR 0 "register_operand" "=r")
4981         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
4982                    UNSPEC_GOTSMALLTLS))]
4983   ""
4984   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
4985   [(set_attr "type" "load1")
4986    (set_attr "length" "8")]
4989 (define_insn "tlsie_small_sidi"
4990   [(set (match_operand:DI 0 "register_operand" "=r")
4991         (zero_extend:DI
4992           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
4993                       UNSPEC_GOTSMALLTLS)))]
4994   ""
4995   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
4996   [(set_attr "type" "load1")
4997    (set_attr "length" "8")]
5000 (define_insn "tlsie_tiny_<mode>"
5001   [(set (match_operand:PTR 0 "register_operand" "=&r")
5002         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5003                      (match_operand:PTR 2 "register_operand" "r")]
5004                    UNSPEC_GOTTINYTLS))]
5005   ""
5006   "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5007   [(set_attr "type" "multiple")
5008    (set_attr "length" "8")]
5011 (define_insn "tlsie_tiny_sidi"
5012   [(set (match_operand:DI 0 "register_operand" "=&r")
5013         (zero_extend:DI
5014           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5015                       (match_operand:DI 2 "register_operand" "r")
5016                       ]
5017                       UNSPEC_GOTTINYTLS)))]
5018   ""
5019   "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5020   [(set_attr "type" "multiple")
5021    (set_attr "length" "8")]
5024 (define_insn "tlsle12_<mode>"
5025   [(set (match_operand:P 0 "register_operand" "=r")
5026         (unspec:P [(match_operand:P 1 "register_operand" "r")
5027                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5028                    UNSPEC_TLSLE12))]
5029   ""
5030   "add\\t%<w>0, %<w>1, #%L2";
5031   [(set_attr "type" "alu_sreg")
5032    (set_attr "length" "4")]
5035 (define_insn "tlsle24_<mode>"
5036   [(set (match_operand:P 0 "register_operand" "=r")
5037         (unspec:P [(match_operand:P 1 "register_operand" "r")
5038                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5039                    UNSPEC_TLSLE24))]
5040   ""
5041   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5042   [(set_attr "type" "multiple")
5043    (set_attr "length" "8")]
5046 (define_insn "tlsle32_<mode>"
5047   [(set (match_operand:P 0 "register_operand" "=r")
5048         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5049                    UNSPEC_TLSLE32))]
5050   ""
5051   "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5052   [(set_attr "type" "multiple")
5053    (set_attr "length" "8")]
5056 (define_insn "tlsle48_<mode>"
5057   [(set (match_operand:P 0 "register_operand" "=r")
5058         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5059                    UNSPEC_TLSLE48))]
5060   ""
5061   "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5062   [(set_attr "type" "multiple")
5063    (set_attr "length" "12")]
5066 (define_insn "tlsdesc_small_<mode>"
5067   [(set (reg:PTR R0_REGNUM)
5068         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5069                    UNSPEC_TLSDESC))
5070    (clobber (reg:DI LR_REGNUM))
5071    (clobber (reg:CC CC_REGNUM))
5072    (clobber (match_scratch:DI 1 "=r"))]
5073   "TARGET_TLS_DESC"
5074   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5075   [(set_attr "type" "call")
5076    (set_attr "length" "16")])
5078 (define_insn "stack_tie"
5079   [(set (mem:BLK (scratch))
5080         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5081                      (match_operand:DI 1 "register_operand" "rk")]
5082                     UNSPEC_PRLG_STK))]
5083   ""
5084   ""
5085   [(set_attr "length" "0")]
5088 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5089 ;; all of memory.  This blocks insns from being moved across this point.
5091 (define_insn "blockage"
5092   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5093   ""
5094   ""
5095   [(set_attr "length" "0")
5096    (set_attr "type" "block")]
5099 (define_insn "probe_stack_range_<PTR:mode>"
5100   [(set (match_operand:PTR 0 "register_operand" "=r")
5101         (unspec_volatile:PTR [(match_operand:PTR 1 "register_operand" "0")
5102                               (match_operand:PTR 2 "register_operand" "r")]
5103                                UNSPECV_PROBE_STACK_RANGE))]
5104   ""
5106   return aarch64_output_probe_stack_range (operands[0], operands[2]);
5108   [(set_attr "length" "32")]
5111 ;; Named pattern for expanding thread pointer reference.
5112 (define_expand "get_thread_pointerdi"
5113   [(match_operand:DI 0 "register_operand" "=r")]
5114   ""
5116   rtx tmp = aarch64_load_tp (operands[0]);
5117   if (tmp != operands[0])
5118     emit_move_insn (operands[0], tmp);
5119   DONE;
5122 ;; Named patterns for stack smashing protection.
5123 (define_expand "stack_protect_set"
5124   [(match_operand 0 "memory_operand")
5125    (match_operand 1 "memory_operand")]
5126   ""
5128   machine_mode mode = GET_MODE (operands[0]);
5130   emit_insn ((mode == DImode
5131               ? gen_stack_protect_set_di
5132               : gen_stack_protect_set_si) (operands[0], operands[1]));
5133   DONE;
5136 (define_insn "stack_protect_set_<mode>"
5137   [(set (match_operand:PTR 0 "memory_operand" "=m")
5138         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5139          UNSPEC_SP_SET))
5140    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5141   ""
5142   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5143   [(set_attr "length" "12")
5144    (set_attr "type" "multiple")])
5146 (define_expand "stack_protect_test"
5147   [(match_operand 0 "memory_operand")
5148    (match_operand 1 "memory_operand")
5149    (match_operand 2)]
5150   ""
5152   rtx result;
5153   machine_mode mode = GET_MODE (operands[0]);
5155   result = gen_reg_rtx(mode);
5157   emit_insn ((mode == DImode
5158               ? gen_stack_protect_test_di
5159               : gen_stack_protect_test_si) (result,
5160                                             operands[0],
5161                                             operands[1]));
5163   if (mode == DImode)
5164     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5165                                     result, const0_rtx, operands[2]));
5166   else
5167     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5168                                     result, const0_rtx, operands[2]));
5169   DONE;
5172 (define_insn "stack_protect_test_<mode>"
5173   [(set (match_operand:PTR 0 "register_operand" "=r")
5174         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5175                      (match_operand:PTR 2 "memory_operand" "m")]
5176          UNSPEC_SP_TEST))
5177    (clobber (match_scratch:PTR 3 "=&r"))]
5178   ""
5179   "ldr\t%<w>3, %x1\;ldr\t%<w>0, %x2\;eor\t%<w>0, %<w>3, %<w>0"
5180   [(set_attr "length" "12")
5181    (set_attr "type" "multiple")])
5183 ;; Write Floating-point Control Register.
5184 (define_insn "set_fpcr"
5185   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5186   ""
5187   "msr\\tfpcr, %0"
5188   [(set_attr "type" "mrs")])
5190 ;; Read Floating-point Control Register.
5191 (define_insn "get_fpcr"
5192   [(set (match_operand:SI 0 "register_operand" "=r")
5193         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5194   ""
5195   "mrs\\t%0, fpcr"
5196   [(set_attr "type" "mrs")])
5198 ;; Write Floating-point Status Register.
5199 (define_insn "set_fpsr"
5200   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5201   ""
5202   "msr\\tfpsr, %0"
5203   [(set_attr "type" "mrs")])
5205 ;; Read Floating-point Status Register.
5206 (define_insn "get_fpsr"
5207   [(set (match_operand:SI 0 "register_operand" "=r")
5208         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5209   ""
5210   "mrs\\t%0, fpsr"
5211   [(set_attr "type" "mrs")])
5214 ;; Define the subtract-one-and-jump insns so loop.c
5215 ;; knows what to generate.
5216 (define_expand "doloop_end"
5217   [(use (match_operand 0 "" ""))      ; loop pseudo
5218    (use (match_operand 1 "" ""))]     ; label
5219   "optimize > 0 && flag_modulo_sched"
5221   rtx s0;
5222   rtx bcomp;
5223   rtx loc_ref;
5224   rtx cc_reg;
5225   rtx insn;
5226   rtx cmp;
5228   /* Currently SMS relies on the do-loop pattern to recognize loops
5229      where (1) the control part consists of all insns defining and/or
5230      using a certain 'count' register and (2) the loop count can be
5231      adjusted by modifying this register prior to the loop.
5232      ??? The possible introduction of a new block to initialize the
5233      new IV can potentially affect branch optimizations.  */
5235   if (GET_MODE (operands[0]) != DImode)
5236     FAIL;
5238   s0 = operands [0];
5239   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5241   cmp = XVECEXP (PATTERN (insn), 0, 0);
5242   cc_reg = SET_DEST (cmp);
5243   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5244   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5245   emit_jump_insn (gen_rtx_SET (pc_rtx,
5246                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5247                                                      loc_ref, pc_rtx)));
5248   DONE;
5251 ;; AdvSIMD Stuff
5252 (include "aarch64-simd.md")
5254 ;; Atomic Operations
5255 (include "atomics.md")
5257 ;; ldp/stp peephole patterns
5258 (include "aarch64-ldpstp.md")