[AArch64] PR target/78362: Make sure to only take REGNO of a register
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blobbc6d8a2b3c29d5a6da03a90cdd3fbab45907e9a9
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_FCVTZS
79     UNSPEC_FCVTZU
80     UNSPEC_URECPE
81     UNSPEC_FRECPE
82     UNSPEC_FRECPS
83     UNSPEC_FRECPX
84     UNSPEC_FRINTA
85     UNSPEC_FRINTI
86     UNSPEC_FRINTM
87     UNSPEC_FRINTN
88     UNSPEC_FRINTP
89     UNSPEC_FRINTX
90     UNSPEC_FRINTZ
91     UNSPEC_GOTSMALLPIC
92     UNSPEC_GOTSMALLPIC28K
93     UNSPEC_GOTSMALLTLS
94     UNSPEC_GOTTINYPIC
95     UNSPEC_GOTTINYTLS
96     UNSPEC_LD1
97     UNSPEC_LD2
98     UNSPEC_LD2_DUP
99     UNSPEC_LD3
100     UNSPEC_LD3_DUP
101     UNSPEC_LD4
102     UNSPEC_LD4_DUP
103     UNSPEC_LD2_LANE
104     UNSPEC_LD3_LANE
105     UNSPEC_LD4_LANE
106     UNSPEC_MB
107     UNSPEC_NOP
108     UNSPEC_PRLG_STK
109     UNSPEC_RBIT
110     UNSPEC_SCVTF
111     UNSPEC_SISD_NEG
112     UNSPEC_SISD_SSHL
113     UNSPEC_SISD_USHL
114     UNSPEC_SSHL_2S
115     UNSPEC_ST1
116     UNSPEC_ST2
117     UNSPEC_ST3
118     UNSPEC_ST4
119     UNSPEC_ST2_LANE
120     UNSPEC_ST3_LANE
121     UNSPEC_ST4_LANE
122     UNSPEC_TLS
123     UNSPEC_TLSDESC
124     UNSPEC_TLSLE12
125     UNSPEC_TLSLE24
126     UNSPEC_TLSLE32
127     UNSPEC_TLSLE48
128     UNSPEC_UCVTF
129     UNSPEC_USHL_2S
130     UNSPEC_VSTRUCTDUMMY
131     UNSPEC_SP_SET
132     UNSPEC_SP_TEST
133     UNSPEC_RSQRT
134     UNSPEC_RSQRTE
135     UNSPEC_RSQRTS
136     UNSPEC_NZCV
139 (define_c_enum "unspecv" [
140     UNSPECV_EH_RETURN           ; Represent EH_RETURN
141     UNSPECV_GET_FPCR            ; Represent fetch of FPCR content.
142     UNSPECV_SET_FPCR            ; Represent assign of FPCR content.
143     UNSPECV_GET_FPSR            ; Represent fetch of FPSR content.
144     UNSPECV_SET_FPSR            ; Represent assign of FPSR content.
145     UNSPECV_BLOCKAGE            ; Represent a blockage
146     UNSPECV_PROBE_STACK_RANGE   ; Represent stack range probing.
147   ]
150 ;; If further include files are added the defintion of MD_INCLUDES
151 ;; must be updated.
153 (include "constraints.md")
154 (include "predicates.md")
155 (include "iterators.md")
157 ;; -------------------------------------------------------------------
158 ;; Instruction types and attributes
159 ;; -------------------------------------------------------------------
161 ; The "type" attribute is included here from AArch32 backend to be able
162 ; to share pipeline descriptions.
163 (include "../arm/types.md")
165 ;; It is important to set the fp or simd attributes to yes when a pattern
166 ;; alternative uses the FP or SIMD register files, usually signified by use of
167 ;; the 'w' constraint.  This will ensure that the alternative will be
168 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
169 ;; architecture extensions.  If all the alternatives in a pattern use the
170 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
171 ;; or TARGET_SIMD.
173 ;; Attribute that specifies whether or not the instruction touches fp
174 ;; registers.  When this is set to yes for an alternative, that alternative
175 ;; will be disabled when !TARGET_FLOAT.
176 (define_attr "fp" "no,yes" (const_string "no"))
178 ;; Attribute that specifies whether or not the instruction touches simd
179 ;; registers.  When this is set to yes for an alternative, that alternative
180 ;; will be disabled when !TARGET_SIMD.
181 (define_attr "simd" "no,yes" (const_string "no"))
183 (define_attr "length" ""
184   (const_int 4))
186 ;; Attribute that controls whether an alternative is enabled or not.
187 ;; Currently it is only used to disable alternatives which touch fp or simd
188 ;; registers when -mgeneral-regs-only is specified.
189 (define_attr "enabled" "no,yes"
190   (cond [(ior
191         (and (eq_attr "fp" "yes")
192              (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
193         (and (eq_attr "simd" "yes")
194              (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
195              (const_string "no")
196         ] (const_string "yes")))
198 ;; Attribute that specifies whether we are dealing with a branch to a
199 ;; label that is far away, i.e. further away than the maximum/minimum
200 ;; representable in a signed 21-bits number.
201 ;; 0 :=: no
202 ;; 1 :=: yes
203 (define_attr "far_branch" "" (const_int 0))
205 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
206 ;; no predicated insns.
207 (define_attr "predicated" "yes,no" (const_string "no"))
209 ;; -------------------------------------------------------------------
210 ;; Pipeline descriptions and scheduling
211 ;; -------------------------------------------------------------------
213 ;; Processor types.
214 (include "aarch64-tune.md")
216 ;; Scheduling
217 (include "../arm/cortex-a53.md")
218 (include "../arm/cortex-a57.md")
219 (include "../arm/exynos-m1.md")
220 (include "thunderx.md")
221 (include "../arm/xgene1.md")
223 ;; -------------------------------------------------------------------
224 ;; Jumps and other miscellaneous insns
225 ;; -------------------------------------------------------------------
227 (define_insn "indirect_jump"
228   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
229   ""
230   "br\\t%0"
231   [(set_attr "type" "branch")]
234 (define_insn "jump"
235   [(set (pc) (label_ref (match_operand 0 "" "")))]
236   ""
237   "b\\t%l0"
238   [(set_attr "type" "branch")]
241 (define_expand "cbranch<mode>4"
242   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
243                             [(match_operand:GPI 1 "register_operand" "")
244                              (match_operand:GPI 2 "aarch64_plus_operand" "")])
245                            (label_ref (match_operand 3 "" ""))
246                            (pc)))]
247   ""
248   "
249   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
250                                          operands[2]);
251   operands[2] = const0_rtx;
252   "
255 (define_expand "cbranch<mode>4"
256   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
257                             [(match_operand:GPF 1 "register_operand" "")
258                              (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
259                            (label_ref (match_operand 3 "" ""))
260                            (pc)))]
261   ""
262   "
263   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
264                                          operands[2]);
265   operands[2] = const0_rtx;
266   "
269 (define_expand "cbranchcc4"
270   [(set (pc) (if_then_else
271               (match_operator 0 "aarch64_comparison_operator"
272                [(match_operand 1 "cc_register" "")
273                 (match_operand 2 "const0_operand")])
274               (label_ref (match_operand 3 "" ""))
275               (pc)))]
276   ""
277   "")
279 (define_insn "ccmp<mode>"
280   [(set (match_operand:CC 1 "cc_register" "")
281         (if_then_else:CC
282           (match_operator 4 "aarch64_comparison_operator"
283            [(match_operand 0 "cc_register" "")
284             (const_int 0)])
285           (compare:CC
286             (match_operand:GPI 2 "register_operand" "r,r,r")
287             (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
288           (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
289   ""
290   "@
291    ccmp\\t%<w>2, %<w>3, %k5, %m4
292    ccmp\\t%<w>2, %3, %k5, %m4
293    ccmn\\t%<w>2, #%n3, %k5, %m4"
294   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
297 (define_insn "fccmp<mode>"
298   [(set (match_operand:CCFP 1 "cc_register" "")
299         (if_then_else:CCFP
300           (match_operator 4 "aarch64_comparison_operator"
301            [(match_operand 0 "cc_register" "")
302             (const_int 0)])
303           (compare:CCFP
304             (match_operand:GPF 2 "register_operand" "w")
305             (match_operand:GPF 3 "register_operand" "w"))
306           (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
307   "TARGET_FLOAT"
308   "fccmp\\t%<s>2, %<s>3, %k5, %m4"
309   [(set_attr "type" "fccmp<s>")]
312 (define_insn "fccmpe<mode>"
313   [(set (match_operand:CCFPE 1 "cc_register" "")
314          (if_then_else:CCFPE
315           (match_operator 4 "aarch64_comparison_operator"
316            [(match_operand 0 "cc_register" "")
317           (const_int 0)])
318            (compare:CCFPE
319             (match_operand:GPF 2 "register_operand" "w")
320             (match_operand:GPF 3 "register_operand" "w"))
321           (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
322   "TARGET_FLOAT"
323   "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
324   [(set_attr "type" "fccmp<s>")]
327 ;; Expansion of signed mod by a power of 2 using CSNEG.
328 ;; For x0 % n where n is a power of 2 produce:
329 ;; negs   x1, x0
330 ;; and    x0, x0, #(n - 1)
331 ;; and    x1, x1, #(n - 1)
332 ;; csneg  x0, x0, x1, mi
334 (define_expand "mod<mode>3"
335   [(match_operand:GPI 0 "register_operand" "")
336    (match_operand:GPI 1 "register_operand" "")
337    (match_operand:GPI 2 "const_int_operand" "")]
338   ""
339   {
340     HOST_WIDE_INT val = INTVAL (operands[2]);
342     if (val <= 0
343        || exact_log2 (val) <= 0
344        || !aarch64_bitmask_imm (val - 1, <MODE>mode))
345       FAIL;
347     rtx mask = GEN_INT (val - 1);
349     /* In the special case of x0 % 2 we can do the even shorter:
350         cmp    x0, xzr
351         and    x0, x0, 1
352         cneg   x0, x0, lt.  */
353     if (val == 2)
354       {
355         rtx masked = gen_reg_rtx (<MODE>mode);
356         rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
357         emit_insn (gen_and<mode>3 (masked, operands[1], mask));
358         rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
359         emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
360         DONE;
361       }
363     rtx neg_op = gen_reg_rtx (<MODE>mode);
364     rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
366     /* Extract the condition register and mode.  */
367     rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
368     rtx cc_reg = SET_DEST (cmp);
369     rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
371     rtx masked_pos = gen_reg_rtx (<MODE>mode);
372     emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
374     rtx masked_neg = gen_reg_rtx (<MODE>mode);
375     emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
377     emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
378                                        masked_neg, masked_pos));
379     DONE;
380   }
383 (define_insn "condjump"
384   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
385                             [(match_operand 1 "cc_register" "") (const_int 0)])
386                            (label_ref (match_operand 2 "" ""))
387                            (pc)))]
388   ""
389   {
390     if (get_attr_length (insn) == 8)
391       return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
392     else
393       return  "b%m0\\t%l2";
394   }
395   [(set_attr "type" "branch")
396    (set (attr "length")
397         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
398                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
399                       (const_int 4)
400                       (const_int 8)))
401    (set (attr "far_branch")
402         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
403                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
404                       (const_int 0)
405                       (const_int 1)))]
408 ;; For a 24-bit immediate CST we can optimize the compare for equality
409 ;; and branch sequence from:
410 ;;      mov     x0, #imm1
411 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
412 ;;      cmp     x1, x0
413 ;;      b<ne,eq> .Label
414 ;; into the shorter:
415 ;;      sub     x0, x1, #(CST & 0xfff000)
416 ;;      subs    x0, x0, #(CST & 0x000fff)
417 ;;      b<ne,eq> .Label
418 (define_insn_and_split "*compare_condjump<mode>"
419   [(set (pc) (if_then_else (EQL
420                               (match_operand:GPI 0 "register_operand" "r")
421                               (match_operand:GPI 1 "aarch64_imm24" "n"))
422                            (label_ref:P (match_operand 2 "" ""))
423                            (pc)))]
424   "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
425    && !aarch64_plus_operand (operands[1], <MODE>mode)
426    && !reload_completed"
427   "#"
428   "&& true"
429   [(const_int 0)]
430   {
431     HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
432     HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
433     rtx tmp = gen_reg_rtx (<MODE>mode);
434     emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
435     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
436     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
437     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
438     emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
439     DONE;
440   }
443 (define_expand "casesi"
444   [(match_operand:SI 0 "register_operand" "")   ; Index
445    (match_operand:SI 1 "const_int_operand" "")  ; Lower bound
446    (match_operand:SI 2 "const_int_operand" "")  ; Total range
447    (match_operand:DI 3 "" "")                   ; Table label
448    (match_operand:DI 4 "" "")]                  ; Out of range label
449   ""
450   {
451     if (operands[1] != const0_rtx)
452       {
453         rtx reg = gen_reg_rtx (SImode);
455         /* Canonical RTL says that if you have:
457            (minus (X) (CONST))
459            then this should be emitted as:
461            (plus (X) (-CONST))
463            The use of trunc_int_for_mode ensures that the resulting
464            constant can be represented in SImode, this is important
465            for the corner case where operand[1] is INT_MIN.  */
467         operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
469         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
470               (operands[1], SImode))
471           operands[1] = force_reg (SImode, operands[1]);
472         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
473         operands[0] = reg;
474       }
476     if (!aarch64_plus_operand (operands[2], SImode))
477       operands[2] = force_reg (SImode, operands[2]);
478     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
479                                                  const0_rtx),
480                                     operands[0], operands[2], operands[4]));
482     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
483     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
484                                          operands[3]));
485     DONE;
486   }
489 (define_insn "casesi_dispatch"
490   [(parallel
491     [(set (pc)
492           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
493                            (match_operand:SI 1 "register_operand" "r")]
494                         UNSPEC_CASESI)))
495      (clobber (reg:CC CC_REGNUM))
496      (clobber (match_scratch:DI 3 "=r"))
497      (clobber (match_scratch:DI 4 "=r"))
498      (use (label_ref (match_operand 2 "" "")))])]
499   ""
500   "*
501   return aarch64_output_casesi (operands);
502   "
503   [(set_attr "length" "16")
504    (set_attr "type" "branch")]
507 (define_insn "nop"
508   [(unspec[(const_int 0)] UNSPEC_NOP)]
509   ""
510   "nop"
511   [(set_attr "type" "no_insn")]
514 (define_insn "prefetch"
515   [(prefetch (match_operand:DI 0 "register_operand" "r")
516             (match_operand:QI 1 "const_int_operand" "")
517             (match_operand:QI 2 "const_int_operand" ""))]
518   ""
519   {
520     const char * pftype[2][4] = 
521     {
522       {"prfm\\tPLDL1STRM, %a0",
523        "prfm\\tPLDL3KEEP, %a0",
524        "prfm\\tPLDL2KEEP, %a0",
525        "prfm\\tPLDL1KEEP, %a0"},
526       {"prfm\\tPSTL1STRM, %a0",
527        "prfm\\tPSTL3KEEP, %a0",
528        "prfm\\tPSTL2KEEP, %a0",
529        "prfm\\tPSTL1KEEP, %a0"},
530     };
532     int locality = INTVAL (operands[2]);
534     gcc_assert (IN_RANGE (locality, 0, 3));
536     return pftype[INTVAL(operands[1])][locality];
537   }
538   [(set_attr "type" "load1")]
541 (define_insn "trap"
542   [(trap_if (const_int 1) (const_int 8))]
543   ""
544   "brk #1000"
545   [(set_attr "type" "trap")])
547 (define_expand "prologue"
548   [(clobber (const_int 0))]
549   ""
550   "
551   aarch64_expand_prologue ();
552   DONE;
553   "
556 (define_expand "epilogue"
557   [(clobber (const_int 0))]
558   ""
559   "
560   aarch64_expand_epilogue (false);
561   DONE;
562   "
565 (define_expand "sibcall_epilogue"
566   [(clobber (const_int 0))]
567   ""
568   "
569   aarch64_expand_epilogue (true);
570   DONE;
571   "
574 (define_insn "*do_return"
575   [(return)]
576   ""
577   "ret"
578   [(set_attr "type" "branch")]
581 (define_expand "return"
582   [(simple_return)]
583   "aarch64_use_return_insn_p ()"
584   ""
587 (define_insn "simple_return"
588   [(simple_return)]
589   ""
590   "ret"
591   [(set_attr "type" "branch")]
594 (define_insn "eh_return"
595   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
596     UNSPECV_EH_RETURN)]
597   ""
598   "#"
599   [(set_attr "type" "branch")]
603 (define_split
604   [(unspec_volatile [(match_operand:DI 0 "register_operand" "")]
605     UNSPECV_EH_RETURN)]
606   "reload_completed"
607   [(set (match_dup 1) (match_dup 0))]
608   {
609     operands[1] = aarch64_final_eh_return_addr ();
610   }
613 (define_insn "*cb<optab><mode>1"
614   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
615                                 (const_int 0))
616                            (label_ref (match_operand 1 "" ""))
617                            (pc)))]
618   ""
619   {
620     if (get_attr_length (insn) == 8)
621       return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
622     else
623       return "<cbz>\\t%<w>0, %l1";
624   }
625   [(set_attr "type" "branch")
626    (set (attr "length")
627         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
628                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
629                       (const_int 4)
630                       (const_int 8)))
631    (set (attr "far_branch")
632         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
633                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
634                       (const_int 0)
635                       (const_int 1)))]
638 (define_insn "*tb<optab><mode>1"
639   [(set (pc) (if_then_else
640               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
641                                     (const_int 1)
642                                     (match_operand 1
643                                       "aarch64_simd_shift_imm_<mode>" "n"))
644                    (const_int 0))
645              (label_ref (match_operand 2 "" ""))
646              (pc)))
647    (clobber (reg:CC CC_REGNUM))]
648   ""
649   {
650     if (get_attr_length (insn) == 8)
651       {
652         if (get_attr_far_branch (insn) == 1)
653           return aarch64_gen_far_branch (operands, 2, "Ltb",
654                                          "<inv_tb>\\t%<w>0, %1, ");
655         else
656           {
657             operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
658             return "tst\t%<w>0, %1\;<bcond>\t%l2";
659           }
660       }
661     else
662       return "<tbz>\t%<w>0, %1, %l2";
663   }
664   [(set_attr "type" "branch")
665    (set (attr "length")
666         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
667                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
668                       (const_int 4)
669                       (const_int 8)))
670    (set (attr "far_branch")
671         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
672                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
673                       (const_int 0)
674                       (const_int 1)))]
678 (define_insn "*cb<optab><mode>1"
679   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
680                                  (const_int 0))
681                            (label_ref (match_operand 1 "" ""))
682                            (pc)))
683    (clobber (reg:CC CC_REGNUM))]
684   ""
685   {
686     if (get_attr_length (insn) == 8)
687       {
688         if (get_attr_far_branch (insn) == 1)
689           return aarch64_gen_far_branch (operands, 1, "Ltb",
690                                          "<inv_tb>\\t%<w>0, <sizem1>, ");
691         else
692           {
693             char buf[64];
694             uint64_t val = ((uint64_t) 1)
695                 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
696             sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
697             output_asm_insn (buf, operands);
698             return "<bcond>\t%l1";
699           }
700       }
701     else
702       return "<tbz>\t%<w>0, <sizem1>, %l1";
703   }
704   [(set_attr "type" "branch")
705    (set (attr "length")
706         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
707                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
708                       (const_int 4)
709                       (const_int 8)))
710    (set (attr "far_branch")
711         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
712                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
713                       (const_int 0)
714                       (const_int 1)))]
717 ;; -------------------------------------------------------------------
718 ;; Subroutine calls and sibcalls
719 ;; -------------------------------------------------------------------
721 (define_expand "call_internal"
722   [(parallel [(call (match_operand 0 "memory_operand" "")
723                     (match_operand 1 "general_operand" ""))
724               (use (match_operand 2 "" ""))
725               (clobber (reg:DI LR_REGNUM))])])
727 (define_expand "call"
728   [(parallel [(call (match_operand 0 "memory_operand" "")
729                     (match_operand 1 "general_operand" ""))
730               (use (match_operand 2 "" ""))
731               (clobber (reg:DI LR_REGNUM))])]
732   ""
733   "
734   {
735     rtx callee, pat;
737     /* In an untyped call, we can get NULL for operand 2.  */
738     if (operands[2] == NULL)
739       operands[2] = const0_rtx;
741     /* Decide if we should generate indirect calls by loading the
742        64-bit address of the callee into a register before performing
743        the branch-and-link.  */
744     callee = XEXP (operands[0], 0);
745     if (GET_CODE (callee) == SYMBOL_REF
746         ? (aarch64_is_long_call_p (callee)
747            || aarch64_is_noplt_call_p (callee))
748         : !REG_P (callee))
749       XEXP (operands[0], 0) = force_reg (Pmode, callee);
751     pat = gen_call_internal (operands[0], operands[1], operands[2]);
752     aarch64_emit_call_insn (pat);
753     DONE;
754   }"
757 (define_insn "*call_reg"
758   [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
759          (match_operand 1 "" ""))
760    (use (match_operand 2 "" ""))
761    (clobber (reg:DI LR_REGNUM))]
762   ""
763   "blr\\t%0"
764   [(set_attr "type" "call")]
767 (define_insn "*call_symbol"
768   [(call (mem:DI (match_operand:DI 0 "" ""))
769          (match_operand 1 "" ""))
770    (use (match_operand 2 "" ""))
771    (clobber (reg:DI LR_REGNUM))]
772   "GET_CODE (operands[0]) == SYMBOL_REF
773    && !aarch64_is_long_call_p (operands[0])
774    && !aarch64_is_noplt_call_p (operands[0])"
775   "bl\\t%a0"
776   [(set_attr "type" "call")]
779 (define_expand "call_value_internal"
780   [(parallel [(set (match_operand 0 "" "")
781                    (call (match_operand 1 "memory_operand" "")
782                          (match_operand 2 "general_operand" "")))
783               (use (match_operand 3 "" ""))
784               (clobber (reg:DI LR_REGNUM))])])
786 (define_expand "call_value"
787   [(parallel [(set (match_operand 0 "" "")
788                    (call (match_operand 1 "memory_operand" "")
789                          (match_operand 2 "general_operand" "")))
790               (use (match_operand 3 "" ""))
791               (clobber (reg:DI LR_REGNUM))])]
792   ""
793   "
794   {
795     rtx callee, pat;
797     /* In an untyped call, we can get NULL for operand 3.  */
798     if (operands[3] == NULL)
799       operands[3] = const0_rtx;
801     /* Decide if we should generate indirect calls by loading the
802        64-bit address of the callee into a register before performing
803        the branch-and-link.  */
804     callee = XEXP (operands[1], 0);
805     if (GET_CODE (callee) == SYMBOL_REF
806         ? (aarch64_is_long_call_p (callee)
807            || aarch64_is_noplt_call_p (callee))
808         : !REG_P (callee))
809       XEXP (operands[1], 0) = force_reg (Pmode, callee);
811     pat = gen_call_value_internal (operands[0], operands[1], operands[2],
812                                    operands[3]);
813     aarch64_emit_call_insn (pat);
814     DONE;
815   }"
818 (define_insn "*call_value_reg"
819   [(set (match_operand 0 "" "")
820         (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
821                       (match_operand 2 "" "")))
822    (use (match_operand 3 "" ""))
823    (clobber (reg:DI LR_REGNUM))]
824   ""
825   "blr\\t%1"
826   [(set_attr "type" "call")]
830 (define_insn "*call_value_symbol"
831   [(set (match_operand 0 "" "")
832         (call (mem:DI (match_operand:DI 1 "" ""))
833               (match_operand 2 "" "")))
834    (use (match_operand 3 "" ""))
835    (clobber (reg:DI LR_REGNUM))]
836   "GET_CODE (operands[1]) == SYMBOL_REF
837    && !aarch64_is_long_call_p (operands[1])
838    && !aarch64_is_noplt_call_p (operands[1])"
839   "bl\\t%a1"
840   [(set_attr "type" "call")]
843 (define_expand "sibcall_internal"
844   [(parallel [(call (match_operand 0 "memory_operand" "")
845                     (match_operand 1 "general_operand" ""))
846               (return)
847               (use (match_operand 2 "" ""))])])
849 (define_expand "sibcall"
850   [(parallel [(call (match_operand 0 "memory_operand" "")
851                     (match_operand 1 "general_operand" ""))
852               (return)
853               (use (match_operand 2 "" ""))])]
854   ""
855   {
856     rtx pat;
857     rtx callee = XEXP (operands[0], 0);
858     if (!REG_P (callee)
859        && ((GET_CODE (callee) != SYMBOL_REF)
860            || aarch64_is_noplt_call_p (callee)))
861       XEXP (operands[0], 0) = force_reg (Pmode, callee);
863     if (operands[2] == NULL_RTX)
864       operands[2] = const0_rtx;
866     pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
867     aarch64_emit_call_insn (pat);
868     DONE;
869   }
872 (define_expand "sibcall_value_internal"
873   [(parallel [(set (match_operand 0 "" "")
874                    (call (match_operand 1 "memory_operand" "")
875                          (match_operand 2 "general_operand" "")))
876               (return)
877               (use (match_operand 3 "" ""))])])
879 (define_expand "sibcall_value"
880   [(parallel [(set (match_operand 0 "" "")
881                    (call (match_operand 1 "memory_operand" "")
882                          (match_operand 2 "general_operand" "")))
883               (return)
884               (use (match_operand 3 "" ""))])]
885   ""
886   {
887     rtx pat;
888     rtx callee = XEXP (operands[1], 0);
889     if (!REG_P (callee)
890        && ((GET_CODE (callee) != SYMBOL_REF)
891            || aarch64_is_noplt_call_p (callee)))
892       XEXP (operands[1], 0) = force_reg (Pmode, callee);
894     if (operands[3] == NULL_RTX)
895       operands[3] = const0_rtx;
897     pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
898                                       operands[3]);
899     aarch64_emit_call_insn (pat);
900     DONE;
901   }
904 (define_insn "*sibcall_insn"
905   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
906          (match_operand 1 "" ""))
907    (return)
908    (use (match_operand 2 "" ""))]
909   "SIBLING_CALL_P (insn)"
910   "@
911    br\\t%0
912    b\\t%a0"
913   [(set_attr "type" "branch, branch")]
916 (define_insn "*sibcall_value_insn"
917   [(set (match_operand 0 "" "")
918         (call (mem:DI
919                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
920               (match_operand 2 "" "")))
921    (return)
922    (use (match_operand 3 "" ""))]
923   "SIBLING_CALL_P (insn)"
924   "@
925    br\\t%1
926    b\\t%a1"
927   [(set_attr "type" "branch, branch")]
930 ;; Call subroutine returning any type.
932 (define_expand "untyped_call"
933   [(parallel [(call (match_operand 0 "")
934                     (const_int 0))
935               (match_operand 1 "")
936               (match_operand 2 "")])]
937   ""
939   int i;
941   emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
943   for (i = 0; i < XVECLEN (operands[2], 0); i++)
944     {
945       rtx set = XVECEXP (operands[2], 0, i);
946       emit_move_insn (SET_DEST (set), SET_SRC (set));
947     }
949   /* The optimizer does not know that the call sets the function value
950      registers we stored in the result block.  We avoid problems by
951      claiming that all hard registers are used and clobbered at this
952      point.  */
953   emit_insn (gen_blockage ());
954   DONE;
957 ;; -------------------------------------------------------------------
958 ;; Moves
959 ;; -------------------------------------------------------------------
961 (define_expand "mov<mode>"
962   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
963         (match_operand:SHORT 1 "general_operand" ""))]
964   ""
965   "
966     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
967       operands[1] = force_reg (<MODE>mode, operands[1]);
968   "
971 (define_insn "*mov<mode>_aarch64"
972   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,   *w,r,*w, m, m, r,*w,*w")
973         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
974   "(register_operand (operands[0], <MODE>mode)
975     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
977    switch (which_alternative)
978      {
979      case 0:
980        return "mov\t%w0, %w1";
981      case 1:
982        return "mov\t%w0, %1";
983      case 2:
984        return aarch64_output_scalar_simd_mov_immediate (operands[1],
985                                                         <MODE>mode);
986      case 3:
987        return "ldr<size>\t%w0, %1";
988      case 4:
989        return "ldr\t%<size>0, %1";
990      case 5:
991        return "str<size>\t%w1, %0";
992      case 6:
993        return "str\t%<size>1, %0";
994      case 7:
995        return "umov\t%w0, %1.<v>[0]";
996      case 8:
997        return "dup\t%0.<Vallxd>, %w1";
998      case 9:
999        return "dup\t%<Vetype>0, %1.<v>[0]";
1000      default:
1001        gcc_unreachable ();
1002      }
1004   [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
1005                      neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1006    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
1009 (define_expand "mov<mode>"
1010   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
1011         (match_operand:GPI 1 "general_operand" ""))]
1012   ""
1013   "
1014     if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
1015         && <MODE>mode == DImode
1016         && aarch64_split_dimode_const_store (operands[0], operands[1]))
1017       DONE;
1019     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1020       operands[1] = force_reg (<MODE>mode, operands[1]);
1022     /* FIXME: RR we still need to fix up what we are doing with
1023        symbol_refs and other types of constants.  */
1024     if (CONSTANT_P (operands[1])
1025         && !CONST_INT_P (operands[1]))
1026      {
1027        aarch64_expand_mov_immediate (operands[0], operands[1]);
1028        DONE;
1029      }
1030   "
1033 (define_insn_and_split "*movsi_aarch64"
1034   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r  ,*w, r,*w")
1035         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
1036   "(register_operand (operands[0], SImode)
1037     || aarch64_reg_or_zero (operands[1], SImode))"
1038   "@
1039    mov\\t%w0, %w1
1040    mov\\t%w0, %w1
1041    mov\\t%w0, %w1
1042    mov\\t%w0, %1
1043    #
1044    ldr\\t%w0, %1
1045    ldr\\t%s0, %1
1046    str\\t%w1, %0
1047    str\\t%s1, %0
1048    adr\\t%x0, %a1
1049    adrp\\t%x0, %A1
1050    fmov\\t%s0, %w1
1051    fmov\\t%w0, %s1
1052    fmov\\t%s0, %s1"
1053    "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1054     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1055    [(const_int 0)]
1056    "{
1057        aarch64_expand_mov_immediate (operands[0], operands[1]);
1058        DONE;
1059     }"
1060   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1061                      adr,adr,f_mcr,f_mrc,fmov")
1062    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
1065 (define_insn_and_split "*movdi_aarch64"
1066   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r,  *w, r,*w,w")
1067         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
1068   "(register_operand (operands[0], DImode)
1069     || aarch64_reg_or_zero (operands[1], DImode))"
1070   "@
1071    mov\\t%x0, %x1
1072    mov\\t%0, %x1
1073    mov\\t%x0, %1
1074    mov\\t%x0, %1
1075    #
1076    ldr\\t%x0, %1
1077    ldr\\t%d0, %1
1078    str\\t%x1, %0
1079    str\\t%d1, %0
1080    adr\\t%x0, %a1
1081    adrp\\t%x0, %A1
1082    fmov\\t%d0, %x1
1083    fmov\\t%x0, %d1
1084    fmov\\t%d0, %d1
1085    movi\\t%d0, %1"
1086    "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1087     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1088    [(const_int 0)]
1089    "{
1090        aarch64_expand_mov_immediate (operands[0], operands[1]);
1091        DONE;
1092     }"
1093   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
1094                      adr,adr,f_mcr,f_mrc,fmov,neon_move")
1095    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1096    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
1099 (define_insn "insv_imm<mode>"
1100   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1101                           (const_int 16)
1102                           (match_operand:GPI 1 "const_int_operand" "n"))
1103         (match_operand:GPI 2 "const_int_operand" "n"))]
1104   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1105    && UINTVAL (operands[1]) % 16 == 0"
1106   "movk\\t%<w>0, %X2, lsl %1"
1107   [(set_attr "type" "mov_imm")]
1110 (define_expand "movti"
1111   [(set (match_operand:TI 0 "nonimmediate_operand" "")
1112         (match_operand:TI 1 "general_operand" ""))]
1113   ""
1114   "
1115     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1116       operands[1] = force_reg (TImode, operands[1]);
1117   "
1120 (define_insn "*movti_aarch64"
1121   [(set (match_operand:TI 0
1122          "nonimmediate_operand"  "=r, *w,r ,*w,r  ,Ump,Ump,*w,m")
1123         (match_operand:TI 1
1124          "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r  ,Z  , m,*w"))]
1125   "(register_operand (operands[0], TImode)
1126     || aarch64_reg_or_zero (operands[1], TImode))"
1127   "@
1128    #
1129    #
1130    #
1131    orr\\t%0.16b, %1.16b, %1.16b
1132    ldp\\t%0, %H0, %1
1133    stp\\t%1, %H1, %0
1134    stp\\txzr, xzr, %0
1135    ldr\\t%q0, %1
1136    str\\t%q1, %0"
1137   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1138                              load2,store2,store2,f_loadd,f_stored")
1139    (set_attr "length" "8,8,8,4,4,4,4,4,4")
1140    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1141    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1144 ;; Split a TImode register-register or register-immediate move into
1145 ;; its component DImode pieces, taking care to handle overlapping
1146 ;; source and dest registers.
1147 (define_split
1148    [(set (match_operand:TI 0 "register_operand" "")
1149          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1150   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1151   [(const_int 0)]
1153   aarch64_split_128bit_move (operands[0], operands[1]);
1154   DONE;
1157 (define_expand "mov<mode>"
1158   [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1159         (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1160   ""
1161   {
1162     if (!TARGET_FLOAT)
1163       {
1164         aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1165         FAIL;
1166       }
1168     if (GET_CODE (operands[0]) == MEM
1169         && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1170               && aarch64_float_const_zero_rtx_p (operands[1])))
1171       operands[1] = force_reg (<MODE>mode, operands[1]);
1172   }
1175 (define_insn "*movhf_aarch64"
1176   [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w  ,?r,w,w,m,r,m ,r")
1177         (match_operand:HF 1 "general_operand"      "Y ,?rY, w,w,m,w,m,rY,r"))]
1178   "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1179     || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1180   "@
1181    movi\\t%0.4h, #0
1182    mov\\t%0.h[0], %w1
1183    umov\\t%w0, %1.h[0]
1184    mov\\t%0.h[0], %1.h[0]
1185    ldr\\t%h0, %1
1186    str\\t%h1, %0
1187    ldrh\\t%w0, %1
1188    strh\\t%w1, %0
1189    mov\\t%w0, %w1"
1190   [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
1191                      f_loads,f_stores,load1,store1,mov_reg")
1192    (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
1195 (define_insn "*movsf_aarch64"
1196   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1197         (match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1198   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1199     || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1200   "@
1201    movi\\t%0.2s, #0
1202    fmov\\t%s0, %w1
1203    fmov\\t%w0, %s1
1204    fmov\\t%s0, %s1
1205    fmov\\t%s0, %1
1206    ldr\\t%s0, %1
1207    str\\t%s1, %0
1208    ldr\\t%w0, %1
1209    str\\t%w1, %0
1210    mov\\t%w0, %w1"
1211   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
1212                      f_loads,f_stores,load1,store1,mov_reg")
1213    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1216 (define_insn "*movdf_aarch64"
1217   [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w,m,r,m ,r")
1218         (match_operand:DF 1 "general_operand"      "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
1219   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1220     || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1221   "@
1222    movi\\t%d0, #0
1223    fmov\\t%d0, %x1
1224    fmov\\t%x0, %d1
1225    fmov\\t%d0, %d1
1226    fmov\\t%d0, %1
1227    ldr\\t%d0, %1
1228    str\\t%d1, %0
1229    ldr\\t%x0, %1
1230    str\\t%x1, %0
1231    mov\\t%x0, %x1"
1232   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
1233                      f_loadd,f_stored,load1,store1,mov_reg")
1234    (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
1237 (define_insn "*movtf_aarch64"
1238   [(set (match_operand:TF 0
1239          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump,Ump")
1240         (match_operand:TF 1
1241          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,Ump,?r ,Y"))]
1242   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1243     || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1244   "@
1245    orr\\t%0.16b, %1.16b, %1.16b
1246    #
1247    #
1248    #
1249    movi\\t%0.2d, #0
1250    fmov\\t%s0, wzr
1251    ldr\\t%q0, %1
1252    str\\t%q1, %0
1253    ldp\\t%0, %H0, %1
1254    stp\\t%1, %H1, %0
1255    stp\\txzr, xzr, %0"
1256   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1257                      f_loadd,f_stored,load2,store2,store2")
1258    (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1259    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1262 (define_split
1263    [(set (match_operand:TF 0 "register_operand" "")
1264          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1265   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1266   [(const_int 0)]
1267   {
1268     aarch64_split_128bit_move (operands[0], operands[1]);
1269     DONE;
1270   }
1273 ;; 0 is dst
1274 ;; 1 is src
1275 ;; 2 is size of move in bytes
1276 ;; 3 is alignment
1278 (define_expand "movmemdi"
1279   [(match_operand:BLK 0 "memory_operand")
1280    (match_operand:BLK 1 "memory_operand")
1281    (match_operand:DI 2 "immediate_operand")
1282    (match_operand:DI 3 "immediate_operand")]
1283    "!STRICT_ALIGNMENT"
1285   if (aarch64_expand_movmem (operands))
1286     DONE;
1287   FAIL;
1291 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1292 ;; fairly lax checking on the second memory operation.
1293 (define_insn "load_pairsi"
1294   [(set (match_operand:SI 0 "register_operand" "=r,*w")
1295         (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1296    (set (match_operand:SI 2 "register_operand" "=r,*w")
1297         (match_operand:SI 3 "memory_operand" "m,m"))]
1298   "rtx_equal_p (XEXP (operands[3], 0),
1299                 plus_constant (Pmode,
1300                                XEXP (operands[1], 0),
1301                                GET_MODE_SIZE (SImode)))"
1302   "@
1303    ldp\\t%w0, %w2, %1
1304    ldp\\t%s0, %s2, %1"
1305   [(set_attr "type" "load2,neon_load1_2reg")
1306    (set_attr "fp" "*,yes")]
1309 (define_insn "load_pairdi"
1310   [(set (match_operand:DI 0 "register_operand" "=r,*w")
1311         (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1312    (set (match_operand:DI 2 "register_operand" "=r,*w")
1313         (match_operand:DI 3 "memory_operand" "m,m"))]
1314   "rtx_equal_p (XEXP (operands[3], 0),
1315                 plus_constant (Pmode,
1316                                XEXP (operands[1], 0),
1317                                GET_MODE_SIZE (DImode)))"
1318   "@
1319    ldp\\t%x0, %x2, %1
1320    ldp\\t%d0, %d2, %1"
1321   [(set_attr "type" "load2,neon_load1_2reg")
1322    (set_attr "fp" "*,yes")]
1326 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1327 ;; fairly lax checking on the second memory operation.
1328 (define_insn "store_pairsi"
1329   [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1330         (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1331    (set (match_operand:SI 2 "memory_operand" "=m,m")
1332         (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1333   "rtx_equal_p (XEXP (operands[2], 0),
1334                 plus_constant (Pmode,
1335                                XEXP (operands[0], 0),
1336                                GET_MODE_SIZE (SImode)))"
1337   "@
1338    stp\\t%w1, %w3, %0
1339    stp\\t%s1, %s3, %0"
1340   [(set_attr "type" "store2,neon_store1_2reg")
1341    (set_attr "fp" "*,yes")]
1344 (define_insn "store_pairdi"
1345   [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1346         (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1347    (set (match_operand:DI 2 "memory_operand" "=m,m")
1348         (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1349   "rtx_equal_p (XEXP (operands[2], 0),
1350                 plus_constant (Pmode,
1351                                XEXP (operands[0], 0),
1352                                GET_MODE_SIZE (DImode)))"
1353   "@
1354    stp\\t%x1, %x3, %0
1355    stp\\t%d1, %d3, %0"
1356   [(set_attr "type" "store2,neon_store1_2reg")
1357    (set_attr "fp" "*,yes")]
1360 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1361 ;; fairly lax checking on the second memory operation.
1362 (define_insn "load_pairsf"
1363   [(set (match_operand:SF 0 "register_operand" "=w,*r")
1364         (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1365    (set (match_operand:SF 2 "register_operand" "=w,*r")
1366         (match_operand:SF 3 "memory_operand" "m,m"))]
1367   "rtx_equal_p (XEXP (operands[3], 0),
1368                 plus_constant (Pmode,
1369                                XEXP (operands[1], 0),
1370                                GET_MODE_SIZE (SFmode)))"
1371   "@
1372    ldp\\t%s0, %s2, %1
1373    ldp\\t%w0, %w2, %1"
1374   [(set_attr "type" "neon_load1_2reg,load2")
1375    (set_attr "fp" "yes,*")]
1378 (define_insn "load_pairdf"
1379   [(set (match_operand:DF 0 "register_operand" "=w,*r")
1380         (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1381    (set (match_operand:DF 2 "register_operand" "=w,*r")
1382         (match_operand:DF 3 "memory_operand" "m,m"))]
1383   "rtx_equal_p (XEXP (operands[3], 0),
1384                 plus_constant (Pmode,
1385                                XEXP (operands[1], 0),
1386                                GET_MODE_SIZE (DFmode)))"
1387   "@
1388    ldp\\t%d0, %d2, %1
1389    ldp\\t%x0, %x2, %1"
1390   [(set_attr "type" "neon_load1_2reg,load2")
1391    (set_attr "fp" "yes,*")]
1394 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1395 ;; fairly lax checking on the second memory operation.
1396 (define_insn "store_pairsf"
1397   [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1398         (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1399    (set (match_operand:SF 2 "memory_operand" "=m,m")
1400         (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1401   "rtx_equal_p (XEXP (operands[2], 0),
1402                 plus_constant (Pmode,
1403                                XEXP (operands[0], 0),
1404                                GET_MODE_SIZE (SFmode)))"
1405   "@
1406    stp\\t%s1, %s3, %0
1407    stp\\t%w1, %w3, %0"
1408   [(set_attr "type" "neon_store1_2reg,store2")
1409    (set_attr "fp" "yes,*")]
1412 (define_insn "store_pairdf"
1413   [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1414         (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY"))
1415    (set (match_operand:DF 2 "memory_operand" "=m,m")
1416         (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))]
1417   "rtx_equal_p (XEXP (operands[2], 0),
1418                 plus_constant (Pmode,
1419                                XEXP (operands[0], 0),
1420                                GET_MODE_SIZE (DFmode)))"
1421   "@
1422    stp\\t%d1, %d3, %0
1423    stp\\t%x1, %x3, %0"
1424   [(set_attr "type" "neon_store1_2reg,store2")
1425    (set_attr "fp" "yes,*")]
1428 ;; Load pair with post-index writeback.  This is primarily used in function
1429 ;; epilogues.
1430 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1431   [(parallel
1432     [(set (match_operand:P 0 "register_operand" "=k")
1433           (plus:P (match_operand:P 1 "register_operand" "0")
1434                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1435      (set (match_operand:GPI 2 "register_operand" "=r")
1436           (mem:GPI (match_dup 1)))
1437      (set (match_operand:GPI 3 "register_operand" "=r")
1438           (mem:GPI (plus:P (match_dup 1)
1439                    (match_operand:P 5 "const_int_operand" "n"))))])]
1440   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1441   "ldp\\t%<w>2, %<w>3, [%1], %4"
1442   [(set_attr "type" "load2")]
1445 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1446   [(parallel
1447     [(set (match_operand:P 0 "register_operand" "=k")
1448           (plus:P (match_operand:P 1 "register_operand" "0")
1449                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1450      (set (match_operand:GPF 2 "register_operand" "=w")
1451           (mem:GPF (match_dup 1)))
1452      (set (match_operand:GPF 3 "register_operand" "=w")
1453           (mem:GPF (plus:P (match_dup 1)
1454                    (match_operand:P 5 "const_int_operand" "n"))))])]
1455   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1456   "ldp\\t%<w>2, %<w>3, [%1], %4"
1457   [(set_attr "type" "neon_load1_2reg")]
1460 ;; Store pair with pre-index writeback.  This is primarily used in function
1461 ;; prologues.
1462 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1463   [(parallel
1464     [(set (match_operand:P 0 "register_operand" "=&k")
1465           (plus:P (match_operand:P 1 "register_operand" "0")
1466                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1467      (set (mem:GPI (plus:P (match_dup 0)
1468                    (match_dup 4)))
1469           (match_operand:GPI 2 "register_operand" "r"))
1470      (set (mem:GPI (plus:P (match_dup 0)
1471                    (match_operand:P 5 "const_int_operand" "n")))
1472           (match_operand:GPI 3 "register_operand" "r"))])]
1473   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1474   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1475   [(set_attr "type" "store2")]
1478 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1479   [(parallel
1480     [(set (match_operand:P 0 "register_operand" "=&k")
1481           (plus:P (match_operand:P 1 "register_operand" "0")
1482                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1483      (set (mem:GPF (plus:P (match_dup 0)
1484                    (match_dup 4)))
1485           (match_operand:GPF 2 "register_operand" "w"))
1486      (set (mem:GPF (plus:P (match_dup 0)
1487                    (match_operand:P 5 "const_int_operand" "n")))
1488           (match_operand:GPF 3 "register_operand" "w"))])]
1489   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1490   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1491   [(set_attr "type" "neon_store1_2reg<q>")]
1494 ;; -------------------------------------------------------------------
1495 ;; Sign/Zero extension
1496 ;; -------------------------------------------------------------------
1498 (define_expand "<optab>sidi2"
1499   [(set (match_operand:DI 0 "register_operand")
1500         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1501   ""
1504 (define_insn "*extendsidi2_aarch64"
1505   [(set (match_operand:DI 0 "register_operand" "=r,r")
1506         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1507   ""
1508   "@
1509    sxtw\t%0, %w1
1510    ldrsw\t%0, %1"
1511   [(set_attr "type" "extend,load1")]
1514 (define_insn "*load_pair_extendsidi2_aarch64"
1515   [(set (match_operand:DI 0 "register_operand" "=r")
1516         (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1517    (set (match_operand:DI 2 "register_operand" "=r")
1518         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1519   "rtx_equal_p (XEXP (operands[3], 0),
1520                 plus_constant (Pmode,
1521                                XEXP (operands[1], 0),
1522                                GET_MODE_SIZE (SImode)))"
1523   "ldpsw\\t%0, %2, %1"
1524   [(set_attr "type" "load2")]
1527 (define_insn "*zero_extendsidi2_aarch64"
1528   [(set (match_operand:DI 0 "register_operand" "=r,r")
1529         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1530   ""
1531   "@
1532    uxtw\t%0, %w1
1533    ldr\t%w0, %1"
1534   [(set_attr "type" "extend,load1")]
1537 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1538   [(set (match_operand:DI 0 "register_operand" "=r")
1539         (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1540    (set (match_operand:DI 2 "register_operand" "=r")
1541         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1542   "rtx_equal_p (XEXP (operands[3], 0),
1543                 plus_constant (Pmode,
1544                                XEXP (operands[1], 0),
1545                                GET_MODE_SIZE (SImode)))"
1546   "ldp\\t%w0, %w2, %1"
1547   [(set_attr "type" "load2")]
1550 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1551   [(set (match_operand:GPI 0 "register_operand")
1552         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1553   ""
1556 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1557   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1558         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1559   ""
1560   "@
1561    sxt<SHORT:size>\t%<GPI:w>0, %w1
1562    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1563   [(set_attr "type" "extend,load1")]
1566 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1567   [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1568         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1569   ""
1570   "@
1571    and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1572    ldr<SHORT:size>\t%w0, %1
1573    ldr\t%<SHORT:size>0, %1"
1574   [(set_attr "type" "logic_imm,load1,load1")]
1577 (define_expand "<optab>qihi2"
1578   [(set (match_operand:HI 0 "register_operand")
1579         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1580   ""
1583 (define_insn "*extendqihi2_aarch64"
1584   [(set (match_operand:HI 0 "register_operand" "=r,r")
1585         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1586   ""
1587   "@
1588    sxtb\t%w0, %w1
1589    ldrsb\t%w0, %1"
1590   [(set_attr "type" "extend,load1")]
1593 (define_insn "*zero_extendqihi2_aarch64"
1594   [(set (match_operand:HI 0 "register_operand" "=r,r")
1595         (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1596   ""
1597   "@
1598    and\t%w0, %w1, 255
1599    ldrb\t%w0, %1"
1600   [(set_attr "type" "logic_imm,load1")]
1603 ;; -------------------------------------------------------------------
1604 ;; Simple arithmetic
1605 ;; -------------------------------------------------------------------
1607 (define_expand "add<mode>3"
1608   [(set
1609     (match_operand:GPI 0 "register_operand" "")
1610     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1611               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1612   ""
1614   /* If operands[1] is a subreg extract the inner RTX.  */
1615   rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1617   /* If the constant is too large for a single instruction and isn't frame
1618      based, split off the immediate so it is available for CSE.  */
1619   if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1620       && can_create_pseudo_p ()
1621       && (!REG_P (op1)
1622          || !REGNO_PTR_FRAME_P (REGNO (op1))))
1623     operands[2] = force_reg (<MODE>mode, operands[2]);
1626 (define_insn "*add<mode>3_aarch64"
1627   [(set
1628     (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
1629     (plus:GPI
1630      (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
1631      (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
1632   ""
1633   "@
1634   add\\t%<w>0, %<w>1, %2
1635   add\\t%<w>0, %<w>1, %<w>2
1636   add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1637   sub\\t%<w>0, %<w>1, #%n2
1638   #"
1639   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
1640    (set_attr "simd" "*,*,yes,*,*")]
1643 ;; zero_extend version of above
1644 (define_insn "*addsi3_aarch64_uxtw"
1645   [(set
1646     (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1647     (zero_extend:DI
1648      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1649               (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
1650   ""
1651   "@
1652   add\\t%w0, %w1, %2
1653   add\\t%w0, %w1, %w2
1654   sub\\t%w0, %w1, #%n2
1655   #"
1656   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1659 ;; If there's a free register, and we can load the constant with a
1660 ;; single instruction, do so.  This has a chance to improve scheduling.
1661 (define_peephole2
1662   [(match_scratch:GPI 3 "r")
1663    (set (match_operand:GPI 0 "register_operand")
1664         (plus:GPI
1665           (match_operand:GPI 1 "register_operand")
1666           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1667   "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1668   [(set (match_dup 3) (match_dup 2))
1669    (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1672 (define_peephole2
1673   [(match_scratch:SI 3 "r")
1674    (set (match_operand:DI 0 "register_operand")
1675         (zero_extend:DI
1676           (plus:SI
1677             (match_operand:SI 1 "register_operand")
1678             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1679   "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1680   [(set (match_dup 3) (match_dup 2))
1681    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1684 ;; After peephole2 has had a chance to run, split any remaining long
1685 ;; additions into two add immediates.
1686 (define_split
1687   [(set (match_operand:GPI 0 "register_operand")
1688         (plus:GPI
1689           (match_operand:GPI 1 "register_operand")
1690           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1691   "epilogue_completed"
1692   [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1693    (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1694   {
1695     HOST_WIDE_INT i = INTVAL (operands[2]);
1696     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1697     operands[3] = GEN_INT (i - s);
1698     operands[4] = GEN_INT (s);
1699   }
1702 (define_split
1703   [(set (match_operand:DI 0 "register_operand")
1704         (zero_extend:DI
1705           (plus:SI
1706             (match_operand:SI 1 "register_operand")
1707             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1708   "epilogue_completed"
1709   [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1710    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1711   {
1712     HOST_WIDE_INT i = INTVAL (operands[2]);
1713     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1714     operands[3] = GEN_INT (i - s);
1715     operands[4] = GEN_INT (s);
1716     operands[5] = gen_lowpart (SImode, operands[0]);
1717   }
1720 (define_expand "addti3"
1721   [(set (match_operand:TI 0 "register_operand" "")
1722         (plus:TI (match_operand:TI 1 "register_operand" "")
1723                  (match_operand:TI 2 "register_operand" "")))]
1724   ""
1726   rtx low = gen_reg_rtx (DImode);
1727   emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1728                                   gen_lowpart (DImode, operands[2])));
1730   rtx high = gen_reg_rtx (DImode);
1731   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1732                                  gen_highpart (DImode, operands[2])));
1734   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1735   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1736   DONE;
1739 (define_insn "add<mode>3_compare0"
1740   [(set (reg:CC_NZ CC_REGNUM)
1741         (compare:CC_NZ
1742          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1743                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1744          (const_int 0)))
1745    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1746         (plus:GPI (match_dup 1) (match_dup 2)))]
1747   ""
1748   "@
1749   adds\\t%<w>0, %<w>1, %<w>2
1750   adds\\t%<w>0, %<w>1, %2
1751   subs\\t%<w>0, %<w>1, #%n2"
1752   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1755 ;; zero_extend version of above
1756 (define_insn "*addsi3_compare0_uxtw"
1757   [(set (reg:CC_NZ CC_REGNUM)
1758         (compare:CC_NZ
1759          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1760                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1761          (const_int 0)))
1762    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1763         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1764   ""
1765   "@
1766   adds\\t%w0, %w1, %w2
1767   adds\\t%w0, %w1, %2
1768   subs\\t%w0, %w1, #%n2"
1769   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1772 (define_insn "*add<mode>3_compareC_cconly_imm"
1773   [(set (reg:CC_C CC_REGNUM)
1774         (ne:CC_C
1775           (plus:<DWI>
1776             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1777             (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1778           (zero_extend:<DWI>
1779             (plus:GPI
1780               (match_dup 0)
1781               (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1782   "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1783                                  <MODE>mode, operands[1])"
1784   "@
1785   cmn\\t%<w>0, %1
1786   cmp\\t%<w>0, #%n1"
1787   [(set_attr "type" "alus_imm")]
1790 (define_insn "*add<mode>3_compareC_cconly"
1791   [(set (reg:CC_C CC_REGNUM)
1792         (ne:CC_C
1793           (plus:<DWI>
1794             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1795             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1796           (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1797   ""
1798   "cmn\\t%<w>0, %<w>1"
1799   [(set_attr "type" "alus_sreg")]
1802 (define_insn "*add<mode>3_compareC_imm"
1803   [(set (reg:CC_C CC_REGNUM)
1804         (ne:CC_C
1805           (plus:<DWI>
1806             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1807             (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1808           (zero_extend:<DWI>
1809             (plus:GPI
1810               (match_dup 1)
1811               (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1812    (set (match_operand:GPI 0 "register_operand" "=r,r")
1813         (plus:GPI (match_dup 1) (match_dup 2)))]
1814   "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1815                                  <MODE>mode, operands[2])"
1816   "@
1817   adds\\t%<w>0, %<w>1, %2
1818   subs\\t%<w>0, %<w>1, #%n2"
1819   [(set_attr "type" "alus_imm")]
1822 (define_insn "add<mode>3_compareC"
1823   [(set (reg:CC_C CC_REGNUM)
1824         (ne:CC_C
1825           (plus:<DWI>
1826             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1827             (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1828           (zero_extend:<DWI>
1829             (plus:GPI (match_dup 1) (match_dup 2)))))
1830    (set (match_operand:GPI 0 "register_operand" "=r")
1831         (plus:GPI (match_dup 1) (match_dup 2)))]
1832   ""
1833   "adds\\t%<w>0, %<w>1, %<w>2"
1834   [(set_attr "type" "alus_sreg")]
1837 (define_insn "*adds_shift_imm_<mode>"
1838   [(set (reg:CC_NZ CC_REGNUM)
1839         (compare:CC_NZ
1840          (plus:GPI (ASHIFT:GPI 
1841                     (match_operand:GPI 1 "register_operand" "r")
1842                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1843                    (match_operand:GPI 3 "register_operand" "r"))
1844          (const_int 0)))
1845    (set (match_operand:GPI 0 "register_operand" "=r")
1846         (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1847                   (match_dup 3)))]
1848   ""
1849   "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1850   [(set_attr "type" "alus_shift_imm")]
1853 (define_insn "*subs_shift_imm_<mode>"
1854   [(set (reg:CC_NZ CC_REGNUM)
1855         (compare:CC_NZ
1856          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1857                     (ASHIFT:GPI
1858                      (match_operand:GPI 2 "register_operand" "r")
1859                      (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1860          (const_int 0)))
1861    (set (match_operand:GPI 0 "register_operand" "=r")
1862         (minus:GPI (match_dup 1)
1863                    (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1864   ""
1865   "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1866   [(set_attr "type" "alus_shift_imm")]
1869 (define_insn "*adds_mul_imm_<mode>"
1870   [(set (reg:CC_NZ CC_REGNUM)
1871         (compare:CC_NZ
1872          (plus:GPI (mult:GPI
1873                     (match_operand:GPI 1 "register_operand" "r")
1874                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1875                    (match_operand:GPI 3 "register_operand" "r"))
1876          (const_int 0)))
1877    (set (match_operand:GPI 0 "register_operand" "=r")
1878         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1879                   (match_dup 3)))]
1880   ""
1881   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1882   [(set_attr "type" "alus_shift_imm")]
1885 (define_insn "*subs_mul_imm_<mode>"
1886   [(set (reg:CC_NZ CC_REGNUM)
1887         (compare:CC_NZ
1888          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1889                     (mult:GPI
1890                      (match_operand:GPI 2 "register_operand" "r")
1891                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1892          (const_int 0)))
1893    (set (match_operand:GPI 0 "register_operand" "=r")
1894         (minus:GPI (match_dup 1)
1895                    (mult:GPI (match_dup 2) (match_dup 3))))]
1896   ""
1897   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1898   [(set_attr "type" "alus_shift_imm")]
1901 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1902   [(set (reg:CC_NZ CC_REGNUM)
1903         (compare:CC_NZ
1904          (plus:GPI
1905           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1906           (match_operand:GPI 2 "register_operand" "r"))
1907         (const_int 0)))
1908    (set (match_operand:GPI 0 "register_operand" "=r")
1909         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1910   ""
1911   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1912   [(set_attr "type" "alus_ext")]
1915 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1916   [(set (reg:CC_NZ CC_REGNUM)
1917         (compare:CC_NZ
1918          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1919                     (ANY_EXTEND:GPI
1920                      (match_operand:ALLX 2 "register_operand" "r")))
1921         (const_int 0)))
1922    (set (match_operand:GPI 0 "register_operand" "=r")
1923         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1924   ""
1925   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1926   [(set_attr "type" "alus_ext")]
1929 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1930   [(set (reg:CC_NZ CC_REGNUM)
1931         (compare:CC_NZ
1932          (plus:GPI (ashift:GPI 
1933                     (ANY_EXTEND:GPI 
1934                      (match_operand:ALLX 1 "register_operand" "r"))
1935                     (match_operand 2 "aarch64_imm3" "Ui3"))
1936                    (match_operand:GPI 3 "register_operand" "r"))
1937          (const_int 0)))
1938    (set (match_operand:GPI 0 "register_operand" "=rk")
1939         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1940                               (match_dup 2))
1941                   (match_dup 3)))]
1942   ""
1943   "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1944   [(set_attr "type" "alus_ext")]
1947 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1948   [(set (reg:CC_NZ CC_REGNUM)
1949         (compare:CC_NZ
1950          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1951                     (ashift:GPI 
1952                      (ANY_EXTEND:GPI
1953                       (match_operand:ALLX 2 "register_operand" "r"))
1954                      (match_operand 3 "aarch64_imm3" "Ui3")))
1955          (const_int 0)))
1956    (set (match_operand:GPI 0 "register_operand" "=rk")
1957         (minus:GPI (match_dup 1)
1958                    (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1959                                (match_dup 3))))]
1960   ""
1961   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1962   [(set_attr "type" "alus_ext")]
1965 (define_insn "*adds_<optab><mode>_multp2"
1966   [(set (reg:CC_NZ CC_REGNUM)
1967         (compare:CC_NZ
1968          (plus:GPI (ANY_EXTRACT:GPI
1969                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1970                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1971                     (match_operand 3 "const_int_operand" "n")
1972                     (const_int 0))
1973                    (match_operand:GPI 4 "register_operand" "r"))
1974         (const_int 0)))
1975    (set (match_operand:GPI 0 "register_operand" "=r")
1976         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1977                                    (match_dup 3)
1978                                    (const_int 0))
1979                   (match_dup 4)))]
1980   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1981   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1982   [(set_attr "type" "alus_ext")]
1985 (define_insn "*subs_<optab><mode>_multp2"
1986   [(set (reg:CC_NZ CC_REGNUM)
1987         (compare:CC_NZ
1988          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1989                     (ANY_EXTRACT:GPI
1990                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1991                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1992                      (match_operand 3 "const_int_operand" "n")
1993                      (const_int 0)))
1994         (const_int 0)))
1995    (set (match_operand:GPI 0 "register_operand" "=r")
1996         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1997                                   (mult:GPI (match_dup 1) (match_dup 2))
1998                                   (match_dup 3)
1999                                   (const_int 0))))]
2000   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2001   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2002   [(set_attr "type" "alus_ext")]
2005 (define_insn "*add<mode>3nr_compare0"
2006   [(set (reg:CC_NZ CC_REGNUM)
2007         (compare:CC_NZ
2008          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2009                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2010          (const_int 0)))]
2011   ""
2012   "@
2013   cmn\\t%<w>0, %<w>1
2014   cmn\\t%<w>0, %1
2015   cmp\\t%<w>0, #%n1"
2016   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2019 (define_insn "*compare_neg<mode>"
2020   [(set (reg:CC_Z CC_REGNUM)
2021         (compare:CC_Z
2022          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2023          (match_operand:GPI 1 "register_operand" "r")))]
2024   ""
2025   "cmn\\t%<w>1, %<w>0"
2026   [(set_attr "type" "alus_sreg")]
2029 (define_insn "*add_<shift>_<mode>"
2030   [(set (match_operand:GPI 0 "register_operand" "=r")
2031         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2032                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2033                   (match_operand:GPI 3 "register_operand" "r")))]
2034   ""
2035   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2036   [(set_attr "type" "alu_shift_imm")]
2039 ;; zero_extend version of above
2040 (define_insn "*add_<shift>_si_uxtw"
2041   [(set (match_operand:DI 0 "register_operand" "=r")
2042         (zero_extend:DI
2043          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2044                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2045                   (match_operand:SI 3 "register_operand" "r"))))]
2046   ""
2047   "add\\t%w0, %w3, %w1, <shift> %2"
2048   [(set_attr "type" "alu_shift_imm")]
2051 (define_insn "*add_mul_imm_<mode>"
2052   [(set (match_operand:GPI 0 "register_operand" "=r")
2053         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2054                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2055                   (match_operand:GPI 3 "register_operand" "r")))]
2056   ""
2057   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2058   [(set_attr "type" "alu_shift_imm")]
2061 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2062   [(set (match_operand:GPI 0 "register_operand" "=rk")
2063         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2064                   (match_operand:GPI 2 "register_operand" "r")))]
2065   ""
2066   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2067   [(set_attr "type" "alu_ext")]
2070 ;; zero_extend version of above
2071 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2072   [(set (match_operand:DI 0 "register_operand" "=rk")
2073         (zero_extend:DI
2074          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2075                   (match_operand:GPI 2 "register_operand" "r"))))]
2076   ""
2077   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2078   [(set_attr "type" "alu_ext")]
2081 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2082   [(set (match_operand:GPI 0 "register_operand" "=rk")
2083         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2084                                (match_operand:ALLX 1 "register_operand" "r"))
2085                               (match_operand 2 "aarch64_imm3" "Ui3"))
2086                   (match_operand:GPI 3 "register_operand" "r")))]
2087   ""
2088   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2089   [(set_attr "type" "alu_ext")]
2092 ;; zero_extend version of above
2093 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2094   [(set (match_operand:DI 0 "register_operand" "=rk")
2095         (zero_extend:DI
2096          (plus:SI (ashift:SI (ANY_EXTEND:SI
2097                               (match_operand:SHORT 1 "register_operand" "r"))
2098                              (match_operand 2 "aarch64_imm3" "Ui3"))
2099                   (match_operand:SI 3 "register_operand" "r"))))]
2100   ""
2101   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2102   [(set_attr "type" "alu_ext")]
2105 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2106   [(set (match_operand:GPI 0 "register_operand" "=rk")
2107         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2108                              (match_operand:ALLX 1 "register_operand" "r"))
2109                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2110                   (match_operand:GPI 3 "register_operand" "r")))]
2111   ""
2112   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2113   [(set_attr "type" "alu_ext")]
2116 ;; zero_extend version of above
2117 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2118   [(set (match_operand:DI 0 "register_operand" "=rk")
2119         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2120                              (match_operand:SHORT 1 "register_operand" "r"))
2121                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2122                   (match_operand:SI 3 "register_operand" "r"))))]
2123   ""
2124   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2125   [(set_attr "type" "alu_ext")]
2128 (define_insn "*add_<optab><mode>_multp2"
2129   [(set (match_operand:GPI 0 "register_operand" "=rk")
2130         (plus:GPI (ANY_EXTRACT:GPI
2131                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2132                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2133                    (match_operand 3 "const_int_operand" "n")
2134                    (const_int 0))
2135                   (match_operand:GPI 4 "register_operand" "r")))]
2136   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2137   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2138   [(set_attr "type" "alu_ext")]
2141 ;; zero_extend version of above
2142 (define_insn "*add_<optab>si_multp2_uxtw"
2143   [(set (match_operand:DI 0 "register_operand" "=rk")
2144         (zero_extend:DI
2145          (plus:SI (ANY_EXTRACT:SI
2146                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2147                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2148                    (match_operand 3 "const_int_operand" "n")
2149                    (const_int 0))
2150                   (match_operand:SI 4 "register_operand" "r"))))]
2151   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2152   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2153   [(set_attr "type" "alu_ext")]
2156 (define_expand "add<mode>3_carryin"
2157   [(set (match_operand:GPI 0 "register_operand")
2158         (plus:GPI
2159           (plus:GPI
2160             (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2161             (match_operand:GPI 1 "aarch64_reg_or_zero"))
2162           (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2163    ""
2164    ""
2167 ;; Note that add with carry with two zero inputs is matched by cset,
2168 ;; and that add with carry with one zero input is matched by cinc.
2170 (define_insn "*add<mode>3_carryin"
2171   [(set (match_operand:GPI 0 "register_operand" "=r")
2172         (plus:GPI
2173           (plus:GPI
2174             (match_operand:GPI 3 "aarch64_carry_operation" "")
2175             (match_operand:GPI 1 "register_operand" "r"))
2176           (match_operand:GPI 2 "register_operand" "r")))]
2177    ""
2178    "adc\\t%<w>0, %<w>1, %<w>2"
2179   [(set_attr "type" "adc_reg")]
2182 ;; zero_extend version of above
2183 (define_insn "*addsi3_carryin_uxtw"
2184   [(set (match_operand:DI 0 "register_operand" "=r")
2185         (zero_extend:DI
2186           (plus:SI
2187             (plus:SI
2188               (match_operand:SI 3 "aarch64_carry_operation" "")
2189               (match_operand:SI 1 "register_operand" "r"))
2190             (match_operand:SI 2 "register_operand" "r"))))]
2191    ""
2192    "adc\\t%w0, %w1, %w2"
2193   [(set_attr "type" "adc_reg")]
2196 (define_insn "*add_uxt<mode>_shift2"
2197   [(set (match_operand:GPI 0 "register_operand" "=rk")
2198         (plus:GPI (and:GPI
2199                    (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2200                                (match_operand 2 "aarch64_imm3" "Ui3"))
2201                    (match_operand 3 "const_int_operand" "n"))
2202                   (match_operand:GPI 4 "register_operand" "r")))]
2203   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2204   "*
2205   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2206                                            INTVAL (operands[3])));
2207   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2208   [(set_attr "type" "alu_ext")]
2211 ;; zero_extend version of above
2212 (define_insn "*add_uxtsi_shift2_uxtw"
2213   [(set (match_operand:DI 0 "register_operand" "=rk")
2214         (zero_extend:DI
2215          (plus:SI (and:SI
2216                    (ashift:SI (match_operand:SI 1 "register_operand" "r")
2217                               (match_operand 2 "aarch64_imm3" "Ui3"))
2218                    (match_operand 3 "const_int_operand" "n"))
2219                   (match_operand:SI 4 "register_operand" "r"))))]
2220   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2221   "*
2222   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2223                                            INTVAL (operands[3])));
2224   return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2225   [(set_attr "type" "alu_ext")]
2228 (define_insn "*add_uxt<mode>_multp2"
2229   [(set (match_operand:GPI 0 "register_operand" "=rk")
2230         (plus:GPI (and:GPI
2231                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2232                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2233                    (match_operand 3 "const_int_operand" "n"))
2234                   (match_operand:GPI 4 "register_operand" "r")))]
2235   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2236   "*
2237   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2238                                            INTVAL (operands[3])));
2239   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2240   [(set_attr "type" "alu_ext")]
2243 ;; zero_extend version of above
2244 (define_insn "*add_uxtsi_multp2_uxtw"
2245   [(set (match_operand:DI 0 "register_operand" "=rk")
2246         (zero_extend:DI
2247          (plus:SI (and:SI
2248                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2249                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2250                    (match_operand 3 "const_int_operand" "n"))
2251                   (match_operand:SI 4 "register_operand" "r"))))]
2252   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2253   "*
2254   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2255                                            INTVAL (operands[3])));
2256   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2257   [(set_attr "type" "alu_ext")]
2260 (define_insn "subsi3"
2261   [(set (match_operand:SI 0 "register_operand" "=rk")
2262         (minus:SI (match_operand:SI 1 "register_operand" "rk")
2263                   (match_operand:SI 2 "register_operand" "r")))]
2264   ""
2265   "sub\\t%w0, %w1, %w2"
2266   [(set_attr "type" "alu_sreg")]
2269 ;; zero_extend version of above
2270 (define_insn "*subsi3_uxtw"
2271   [(set (match_operand:DI 0 "register_operand" "=rk")
2272         (zero_extend:DI
2273          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2274                    (match_operand:SI 2 "register_operand" "r"))))]
2275   ""
2276   "sub\\t%w0, %w1, %w2"
2277   [(set_attr "type" "alu_sreg")]
2280 (define_insn "subdi3"
2281   [(set (match_operand:DI 0 "register_operand" "=rk,w")
2282         (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2283                   (match_operand:DI 2 "register_operand" "r,w")))]
2284   ""
2285   "@
2286    sub\\t%x0, %x1, %x2
2287    sub\\t%d0, %d1, %d2"
2288   [(set_attr "type" "alu_sreg, neon_sub")
2289    (set_attr "simd" "*,yes")]
2292 (define_expand "subti3"
2293   [(set (match_operand:TI 0 "register_operand" "")
2294         (minus:TI (match_operand:TI 1 "register_operand" "")
2295                   (match_operand:TI 2 "register_operand" "")))]
2296   ""
2298   rtx low = gen_reg_rtx (DImode);
2299   emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2300                                   gen_lowpart (DImode, operands[2])));
2302   rtx high = gen_reg_rtx (DImode);
2303   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2304                                  gen_highpart (DImode, operands[2])));
2306   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2307   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2308   DONE;
2311 (define_insn "*sub<mode>3_compare0"
2312   [(set (reg:CC_NZ CC_REGNUM)
2313         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2314                                   (match_operand:GPI 2 "register_operand" "r"))
2315                        (const_int 0)))
2316    (set (match_operand:GPI 0 "register_operand" "=r")
2317         (minus:GPI (match_dup 1) (match_dup 2)))]
2318   ""
2319   "subs\\t%<w>0, %<w>1, %<w>2"
2320   [(set_attr "type" "alus_sreg")]
2323 ;; zero_extend version of above
2324 (define_insn "*subsi3_compare0_uxtw"
2325   [(set (reg:CC_NZ CC_REGNUM)
2326         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2327                                  (match_operand:SI 2 "register_operand" "r"))
2328                        (const_int 0)))
2329    (set (match_operand:DI 0 "register_operand" "=r")
2330         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2331   ""
2332   "subs\\t%w0, %w1, %w2"
2333   [(set_attr "type" "alus_sreg")]
2336 (define_insn "sub<mode>3_compare1"
2337   [(set (reg:CC CC_REGNUM)
2338         (compare:CC
2339           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2340           (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2341    (set (match_operand:GPI 0 "register_operand" "=r")
2342         (minus:GPI (match_dup 1) (match_dup 2)))]
2343   ""
2344   "subs\\t%<w>0, %<w>1, %<w>2"
2345   [(set_attr "type" "alus_sreg")]
2348 (define_insn "*sub_<shift>_<mode>"
2349   [(set (match_operand:GPI 0 "register_operand" "=r")
2350         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2351                    (ASHIFT:GPI
2352                     (match_operand:GPI 1 "register_operand" "r")
2353                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2354   ""
2355   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2356   [(set_attr "type" "alu_shift_imm")]
2359 ;; zero_extend version of above
2360 (define_insn "*sub_<shift>_si_uxtw"
2361   [(set (match_operand:DI 0 "register_operand" "=r")
2362         (zero_extend:DI
2363          (minus:SI (match_operand:SI 3 "register_operand" "r")
2364                    (ASHIFT:SI
2365                     (match_operand:SI 1 "register_operand" "r")
2366                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2367   ""
2368   "sub\\t%w0, %w3, %w1, <shift> %2"
2369   [(set_attr "type" "alu_shift_imm")]
2372 (define_insn "*sub_mul_imm_<mode>"
2373   [(set (match_operand:GPI 0 "register_operand" "=r")
2374         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2375                    (mult:GPI
2376                     (match_operand:GPI 1 "register_operand" "r")
2377                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2378   ""
2379   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2380   [(set_attr "type" "alu_shift_imm")]
2383 ;; zero_extend version of above
2384 (define_insn "*sub_mul_imm_si_uxtw"
2385   [(set (match_operand:DI 0 "register_operand" "=r")
2386         (zero_extend:DI
2387          (minus:SI (match_operand:SI 3 "register_operand" "r")
2388                    (mult:SI
2389                     (match_operand:SI 1 "register_operand" "r")
2390                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2391   ""
2392   "sub\\t%w0, %w3, %w1, lsl %p2"
2393   [(set_attr "type" "alu_shift_imm")]
2396 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2397   [(set (match_operand:GPI 0 "register_operand" "=rk")
2398         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2399                    (ANY_EXTEND:GPI
2400                     (match_operand:ALLX 2 "register_operand" "r"))))]
2401   ""
2402   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2403   [(set_attr "type" "alu_ext")]
2406 ;; zero_extend version of above
2407 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2408   [(set (match_operand:DI 0 "register_operand" "=rk")
2409         (zero_extend:DI
2410          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2411                    (ANY_EXTEND:SI
2412                     (match_operand:SHORT 2 "register_operand" "r")))))]
2413   ""
2414   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2415   [(set_attr "type" "alu_ext")]
2418 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2419   [(set (match_operand:GPI 0 "register_operand" "=rk")
2420         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2421                    (ashift:GPI (ANY_EXTEND:GPI
2422                                 (match_operand:ALLX 2 "register_operand" "r"))
2423                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
2424   ""
2425   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2426   [(set_attr "type" "alu_ext")]
2429 ;; zero_extend version of above
2430 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2431   [(set (match_operand:DI 0 "register_operand" "=rk")
2432         (zero_extend:DI
2433          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2434                    (ashift:SI (ANY_EXTEND:SI
2435                                (match_operand:SHORT 2 "register_operand" "r"))
2436                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
2437   ""
2438   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2439   [(set_attr "type" "alu_ext")]
2442 (define_insn "*sub_<optab><mode>_multp2"
2443   [(set (match_operand:GPI 0 "register_operand" "=rk")
2444         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2445                    (ANY_EXTRACT:GPI
2446                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2447                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2448                     (match_operand 3 "const_int_operand" "n")
2449                     (const_int 0))))]
2450   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2451   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2452   [(set_attr "type" "alu_ext")]
2455 ;; zero_extend version of above
2456 (define_insn "*sub_<optab>si_multp2_uxtw"
2457   [(set (match_operand:DI 0 "register_operand" "=rk")
2458         (zero_extend:DI
2459          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2460                    (ANY_EXTRACT:SI
2461                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2462                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2463                     (match_operand 3 "const_int_operand" "n")
2464                     (const_int 0)))))]
2465   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2466   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2467   [(set_attr "type" "alu_ext")]
2470 ;; The hardware description is op1 + ~op2 + C.
2471 ;;                           = op1 + (-op2 + 1) + (1 - !C)
2472 ;;                           = op1 - op2 - 1 + 1 - !C
2473 ;;                           = op1 - op2 - !C.
2474 ;; We describe the latter.
2476 (define_insn "*sub<mode>3_carryin0"
2477   [(set (match_operand:GPI 0 "register_operand" "=r")
2478         (minus:GPI
2479           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2480           (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2481    ""
2482    "sbc\\t%<w>0, %<w>1, <w>zr"
2483   [(set_attr "type" "adc_reg")]
2486 ;; zero_extend version of the above
2487 (define_insn "*subsi3_carryin_uxtw"
2488   [(set (match_operand:DI 0 "register_operand" "=r")
2489         (zero_extend:DI
2490           (minus:SI
2491             (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2492             (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2493    ""
2494    "sbc\\t%w0, %w1, wzr"
2495   [(set_attr "type" "adc_reg")]
2498 (define_expand "sub<mode>3_carryin"
2499   [(set (match_operand:GPI 0 "register_operand")
2500         (minus:GPI
2501           (minus:GPI
2502             (match_operand:GPI 1 "aarch64_reg_or_zero")
2503             (match_operand:GPI 2 "register_operand"))
2504           (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2505    ""
2506    ""
2509 (define_insn "*sub<mode>3_carryin"
2510   [(set (match_operand:GPI 0 "register_operand" "=r")
2511         (minus:GPI
2512           (minus:GPI
2513             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2514             (match_operand:GPI 2 "register_operand" "r"))
2515           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2517    ""
2518    "sbc\\t%<w>0, %<w>1, %<w>2"
2519   [(set_attr "type" "adc_reg")]
2522 ;; zero_extend version of the above
2523 (define_insn "*subsi3_carryin_uxtw"
2524   [(set (match_operand:DI 0 "register_operand" "=r")
2525         (zero_extend:DI
2526           (minus:SI
2527             (minus:SI
2528               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2529               (match_operand:SI 2 "register_operand" "r"))
2530             (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2532    ""
2533    "sbc\\t%w0, %w1, %w2"
2534   [(set_attr "type" "adc_reg")]
2537 (define_insn "*sub<mode>3_carryin_alt"
2538   [(set (match_operand:GPI 0 "register_operand" "=r")
2539         (minus:GPI
2540           (minus:GPI
2541             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2542             (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2543           (match_operand:GPI 2 "register_operand" "r")))]
2544    ""
2545    "sbc\\t%<w>0, %<w>1, %<w>2"
2546   [(set_attr "type" "adc_reg")]
2549 ;; zero_extend version of the above
2550 (define_insn "*subsi3_carryin_alt_uxtw"
2551   [(set (match_operand:DI 0 "register_operand" "=r")
2552         (zero_extend:DI
2553           (minus:SI
2554             (minus:SI
2555               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2556               (match_operand:SI 3 "aarch64_borrow_operation" ""))
2557             (match_operand:SI 2 "register_operand" "r"))))]
2558    ""
2559    "sbc\\t%w0, %w1, %w2"
2560   [(set_attr "type" "adc_reg")]
2563 (define_insn "*sub_uxt<mode>_shift2"
2564   [(set (match_operand:GPI 0 "register_operand" "=rk")
2565         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2566                    (and:GPI
2567                     (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2568                                 (match_operand 2 "aarch64_imm3" "Ui3"))
2569                     (match_operand 3 "const_int_operand" "n"))))]
2570   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2571   "*
2572   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2573                                            INTVAL (operands[3])));
2574   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2575   [(set_attr "type" "alu_ext")]
2578 ;; zero_extend version of above
2579 (define_insn "*sub_uxtsi_shift2_uxtw"
2580   [(set (match_operand:DI 0 "register_operand" "=rk")
2581         (zero_extend:DI
2582          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2583                    (and:SI
2584                     (ashift:SI (match_operand:SI 1 "register_operand" "r")
2585                                (match_operand 2 "aarch64_imm3" "Ui3"))
2586                     (match_operand 3 "const_int_operand" "n")))))]
2587   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2588   "*
2589   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2590                                            INTVAL (operands[3])));
2591   return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2592   [(set_attr "type" "alu_ext")]
2595 (define_insn "*sub_uxt<mode>_multp2"
2596   [(set (match_operand:GPI 0 "register_operand" "=rk")
2597         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2598                    (and:GPI
2599                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2600                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2601                     (match_operand 3 "const_int_operand" "n"))))]
2602   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2603   "*
2604   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2605                                            INTVAL (operands[3])));
2606   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2607   [(set_attr "type" "alu_ext")]
2610 ;; zero_extend version of above
2611 (define_insn "*sub_uxtsi_multp2_uxtw"
2612   [(set (match_operand:DI 0 "register_operand" "=rk")
2613         (zero_extend:DI
2614          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2615                    (and:SI
2616                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2617                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2618                     (match_operand 3 "const_int_operand" "n")))))]
2619   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2620   "*
2621   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2622                                            INTVAL (operands[3])));
2623   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2624   [(set_attr "type" "alu_ext")]
2627 (define_expand "abs<mode>2"
2628   [(match_operand:GPI 0 "register_operand" "")
2629    (match_operand:GPI 1 "register_operand" "")]
2630   ""
2631   {
2632     rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2633     rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2634     emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2635     DONE;
2636   }
2639 (define_insn "neg<mode>2"
2640   [(set (match_operand:GPI 0 "register_operand" "=r,w")
2641         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2642   ""
2643   "@
2644    neg\\t%<w>0, %<w>1
2645    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2646   [(set_attr "type" "alu_sreg, neon_neg<q>")
2647    (set_attr "simd" "*,yes")]
2650 ;; zero_extend version of above
2651 (define_insn "*negsi2_uxtw"
2652   [(set (match_operand:DI 0 "register_operand" "=r")
2653         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2654   ""
2655   "neg\\t%w0, %w1"
2656   [(set_attr "type" "alu_sreg")]
2659 (define_insn "*ngc<mode>"
2660   [(set (match_operand:GPI 0 "register_operand" "=r")
2661         (minus:GPI
2662           (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2663           (match_operand:GPI 1 "register_operand" "r")))]
2664   ""
2665   "ngc\\t%<w>0, %<w>1"
2666   [(set_attr "type" "adc_reg")]
2669 (define_insn "*ngcsi_uxtw"
2670   [(set (match_operand:DI 0 "register_operand" "=r")
2671         (zero_extend:DI
2672           (minus:SI
2673             (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2674             (match_operand:SI 1 "register_operand" "r"))))]
2675   ""
2676   "ngc\\t%w0, %w1"
2677   [(set_attr "type" "adc_reg")]
2680 (define_insn "neg<mode>2_compare0"
2681   [(set (reg:CC_NZ CC_REGNUM)
2682         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2683                        (const_int 0)))
2684    (set (match_operand:GPI 0 "register_operand" "=r")
2685         (neg:GPI (match_dup 1)))]
2686   ""
2687   "negs\\t%<w>0, %<w>1"
2688   [(set_attr "type" "alus_sreg")]
2691 ;; zero_extend version of above
2692 (define_insn "*negsi2_compare0_uxtw"
2693   [(set (reg:CC_NZ CC_REGNUM)
2694         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2695                        (const_int 0)))
2696    (set (match_operand:DI 0 "register_operand" "=r")
2697         (zero_extend:DI (neg:SI (match_dup 1))))]
2698   ""
2699   "negs\\t%w0, %w1"
2700   [(set_attr "type" "alus_sreg")]
2703 (define_insn "*neg_<shift><mode>3_compare0"
2704   [(set (reg:CC_NZ CC_REGNUM)
2705         (compare:CC_NZ
2706          (neg:GPI (ASHIFT:GPI
2707                    (match_operand:GPI 1 "register_operand" "r")
2708                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2709          (const_int 0)))
2710    (set (match_operand:GPI 0 "register_operand" "=r")
2711         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2712   ""
2713   "negs\\t%<w>0, %<w>1, <shift> %2"
2714   [(set_attr "type" "alus_shift_imm")]
2717 (define_insn "*neg_<shift>_<mode>2"
2718   [(set (match_operand:GPI 0 "register_operand" "=r")
2719         (neg:GPI (ASHIFT:GPI
2720                   (match_operand:GPI 1 "register_operand" "r")
2721                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2722   ""
2723   "neg\\t%<w>0, %<w>1, <shift> %2"
2724   [(set_attr "type" "alu_shift_imm")]
2727 ;; zero_extend version of above
2728 (define_insn "*neg_<shift>_si2_uxtw"
2729   [(set (match_operand:DI 0 "register_operand" "=r")
2730         (zero_extend:DI
2731          (neg:SI (ASHIFT:SI
2732                   (match_operand:SI 1 "register_operand" "r")
2733                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2734   ""
2735   "neg\\t%w0, %w1, <shift> %2"
2736   [(set_attr "type" "alu_shift_imm")]
2739 (define_insn "*neg_mul_imm_<mode>2"
2740   [(set (match_operand:GPI 0 "register_operand" "=r")
2741         (neg:GPI (mult:GPI
2742                   (match_operand:GPI 1 "register_operand" "r")
2743                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2744   ""
2745   "neg\\t%<w>0, %<w>1, lsl %p2"
2746   [(set_attr "type" "alu_shift_imm")]
2749 ;; zero_extend version of above
2750 (define_insn "*neg_mul_imm_si2_uxtw"
2751   [(set (match_operand:DI 0 "register_operand" "=r")
2752         (zero_extend:DI
2753          (neg:SI (mult:SI
2754                   (match_operand:SI 1 "register_operand" "r")
2755                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2756   ""
2757   "neg\\t%w0, %w1, lsl %p2"
2758   [(set_attr "type" "alu_shift_imm")]
2761 (define_insn "mul<mode>3"
2762   [(set (match_operand:GPI 0 "register_operand" "=r")
2763         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2764                   (match_operand:GPI 2 "register_operand" "r")))]
2765   ""
2766   "mul\\t%<w>0, %<w>1, %<w>2"
2767   [(set_attr "type" "mul")]
2770 ;; zero_extend version of above
2771 (define_insn "*mulsi3_uxtw"
2772   [(set (match_operand:DI 0 "register_operand" "=r")
2773         (zero_extend:DI
2774          (mult:SI (match_operand:SI 1 "register_operand" "r")
2775                   (match_operand:SI 2 "register_operand" "r"))))]
2776   ""
2777   "mul\\t%w0, %w1, %w2"
2778   [(set_attr "type" "mul")]
2781 (define_insn "madd<mode>"
2782   [(set (match_operand:GPI 0 "register_operand" "=r")
2783         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2784                             (match_operand:GPI 2 "register_operand" "r"))
2785                   (match_operand:GPI 3 "register_operand" "r")))]
2786   ""
2787   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2788   [(set_attr "type" "mla")]
2791 ;; zero_extend version of above
2792 (define_insn "*maddsi_uxtw"
2793   [(set (match_operand:DI 0 "register_operand" "=r")
2794         (zero_extend:DI
2795          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2796                            (match_operand:SI 2 "register_operand" "r"))
2797                   (match_operand:SI 3 "register_operand" "r"))))]
2798   ""
2799   "madd\\t%w0, %w1, %w2, %w3"
2800   [(set_attr "type" "mla")]
2803 (define_insn "*msub<mode>"
2804   [(set (match_operand:GPI 0 "register_operand" "=r")
2805         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2806                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2807                              (match_operand:GPI 2 "register_operand" "r"))))]
2809   ""
2810   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2811   [(set_attr "type" "mla")]
2814 ;; zero_extend version of above
2815 (define_insn "*msubsi_uxtw"
2816   [(set (match_operand:DI 0 "register_operand" "=r")
2817         (zero_extend:DI
2818          (minus:SI (match_operand:SI 3 "register_operand" "r")
2819                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2820                             (match_operand:SI 2 "register_operand" "r")))))]
2822   ""
2823   "msub\\t%w0, %w1, %w2, %w3"
2824   [(set_attr "type" "mla")]
2827 (define_insn "*mul<mode>_neg"
2828   [(set (match_operand:GPI 0 "register_operand" "=r")
2829         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2830                   (match_operand:GPI 2 "register_operand" "r")))]
2832   ""
2833   "mneg\\t%<w>0, %<w>1, %<w>2"
2834   [(set_attr "type" "mul")]
2837 ;; zero_extend version of above
2838 (define_insn "*mulsi_neg_uxtw"
2839   [(set (match_operand:DI 0 "register_operand" "=r")
2840         (zero_extend:DI
2841          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2842                   (match_operand:SI 2 "register_operand" "r"))))]
2844   ""
2845   "mneg\\t%w0, %w1, %w2"
2846   [(set_attr "type" "mul")]
2849 (define_insn "<su_optab>mulsidi3"
2850   [(set (match_operand:DI 0 "register_operand" "=r")
2851         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2852                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2853   ""
2854   "<su>mull\\t%0, %w1, %w2"
2855   [(set_attr "type" "<su>mull")]
2858 (define_insn "<su_optab>maddsidi4"
2859   [(set (match_operand:DI 0 "register_operand" "=r")
2860         (plus:DI (mult:DI
2861                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2862                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2863                  (match_operand:DI 3 "register_operand" "r")))]
2864   ""
2865   "<su>maddl\\t%0, %w1, %w2, %3"
2866   [(set_attr "type" "<su>mlal")]
2869 (define_insn "<su_optab>msubsidi4"
2870   [(set (match_operand:DI 0 "register_operand" "=r")
2871         (minus:DI
2872          (match_operand:DI 3 "register_operand" "r")
2873          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2874                   (ANY_EXTEND:DI
2875                    (match_operand:SI 2 "register_operand" "r")))))]
2876   ""
2877   "<su>msubl\\t%0, %w1, %w2, %3"
2878   [(set_attr "type" "<su>mlal")]
2881 (define_insn "*<su_optab>mulsidi_neg"
2882   [(set (match_operand:DI 0 "register_operand" "=r")
2883         (mult:DI (neg:DI
2884                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2885                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2886   ""
2887   "<su>mnegl\\t%0, %w1, %w2"
2888   [(set_attr "type" "<su>mull")]
2891 (define_expand "<su_optab>mulditi3"
2892   [(set (match_operand:TI 0 "register_operand")
2893         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2894                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2895   ""
2897   rtx low = gen_reg_rtx (DImode);
2898   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2900   rtx high = gen_reg_rtx (DImode);
2901   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2903   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2904   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2905   DONE;
2908 ;; The default expansion of multi3 using umuldi3_highpart will perform
2909 ;; the additions in an order that fails to combine into two madd insns.
2910 (define_expand "multi3"
2911   [(set (match_operand:TI 0 "register_operand")
2912         (mult:TI (match_operand:TI 1 "register_operand")
2913                  (match_operand:TI 2 "register_operand")))]
2914   ""
2916   rtx l0 = gen_reg_rtx (DImode);
2917   rtx l1 = gen_lowpart (DImode, operands[1]);
2918   rtx l2 = gen_lowpart (DImode, operands[2]);
2919   rtx h0 = gen_reg_rtx (DImode);
2920   rtx h1 = gen_highpart (DImode, operands[1]);
2921   rtx h2 = gen_highpart (DImode, operands[2]);
2923   emit_insn (gen_muldi3 (l0, l1, l2));
2924   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2925   emit_insn (gen_madddi (h0, h1, l2, h0));
2926   emit_insn (gen_madddi (h0, l1, h2, h0));
2928   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2929   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2930   DONE;
2933 (define_insn "<su>muldi3_highpart"
2934   [(set (match_operand:DI 0 "register_operand" "=r")
2935         (truncate:DI
2936          (lshiftrt:TI
2937           (mult:TI
2938            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2939            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2940           (const_int 64))))]
2941   ""
2942   "<su>mulh\\t%0, %1, %2"
2943   [(set_attr "type" "<su>mull")]
2946 (define_insn "<su_optab>div<mode>3"
2947   [(set (match_operand:GPI 0 "register_operand" "=r")
2948         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2949                      (match_operand:GPI 2 "register_operand" "r")))]
2950   ""
2951   "<su>div\\t%<w>0, %<w>1, %<w>2"
2952   [(set_attr "type" "<su>div")]
2955 ;; zero_extend version of above
2956 (define_insn "*<su_optab>divsi3_uxtw"
2957   [(set (match_operand:DI 0 "register_operand" "=r")
2958         (zero_extend:DI
2959          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2960                      (match_operand:SI 2 "register_operand" "r"))))]
2961   ""
2962   "<su>div\\t%w0, %w1, %w2"
2963   [(set_attr "type" "<su>div")]
2966 ;; -------------------------------------------------------------------
2967 ;; Comparison insns
2968 ;; -------------------------------------------------------------------
2970 (define_insn "cmp<mode>"
2971   [(set (reg:CC CC_REGNUM)
2972         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2973                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2974   ""
2975   "@
2976    cmp\\t%<w>0, %<w>1
2977    cmp\\t%<w>0, %1
2978    cmn\\t%<w>0, #%n1"
2979   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2982 (define_insn "fcmp<mode>"
2983   [(set (reg:CCFP CC_REGNUM)
2984         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2985                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2986    "TARGET_FLOAT"
2987    "@
2988     fcmp\\t%<s>0, #0.0
2989     fcmp\\t%<s>0, %<s>1"
2990   [(set_attr "type" "fcmp<s>")]
2993 (define_insn "fcmpe<mode>"
2994   [(set (reg:CCFPE CC_REGNUM)
2995         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2996                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2997    "TARGET_FLOAT"
2998    "@
2999     fcmpe\\t%<s>0, #0.0
3000     fcmpe\\t%<s>0, %<s>1"
3001   [(set_attr "type" "fcmp<s>")]
3004 (define_insn "*cmp_swp_<shift>_reg<mode>"
3005   [(set (reg:CC_SWP CC_REGNUM)
3006         (compare:CC_SWP (ASHIFT:GPI
3007                          (match_operand:GPI 0 "register_operand" "r")
3008                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3009                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3010   ""
3011   "cmp\\t%<w>2, %<w>0, <shift> %1"
3012   [(set_attr "type" "alus_shift_imm")]
3015 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3016   [(set (reg:CC_SWP CC_REGNUM)
3017         (compare:CC_SWP (ANY_EXTEND:GPI
3018                          (match_operand:ALLX 0 "register_operand" "r"))
3019                         (match_operand:GPI 1 "register_operand" "r")))]
3020   ""
3021   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3022   [(set_attr "type" "alus_ext")]
3025 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3026   [(set (reg:CC_SWP CC_REGNUM)
3027         (compare:CC_SWP (ashift:GPI
3028                          (ANY_EXTEND:GPI
3029                           (match_operand:ALLX 0 "register_operand" "r"))
3030                          (match_operand 1 "aarch64_imm3" "Ui3"))
3031         (match_operand:GPI 2 "register_operand" "r")))]
3032   ""
3033   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3034   [(set_attr "type" "alus_ext")]
3037 ;; -------------------------------------------------------------------
3038 ;; Store-flag and conditional select insns
3039 ;; -------------------------------------------------------------------
3041 (define_expand "cstore<mode>4"
3042   [(set (match_operand:SI 0 "register_operand" "")
3043         (match_operator:SI 1 "aarch64_comparison_operator"
3044          [(match_operand:GPI 2 "register_operand" "")
3045           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3046   ""
3047   "
3048   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3049                                       operands[3]);
3050   operands[3] = const0_rtx;
3051   "
3054 (define_expand "cstorecc4"
3055   [(set (match_operand:SI 0 "register_operand")
3056        (match_operator 1 "aarch64_comparison_operator_mode"
3057         [(match_operand 2 "cc_register")
3058          (match_operand 3 "const0_operand")]))]
3059   ""
3061   emit_insn (gen_rtx_SET (operands[0], operands[1]));
3062   DONE;
3066 (define_expand "cstore<mode>4"
3067   [(set (match_operand:SI 0 "register_operand" "")
3068         (match_operator:SI 1 "aarch64_comparison_operator_mode"
3069          [(match_operand:GPF 2 "register_operand" "")
3070           (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3071   ""
3072   "
3073   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3074                                       operands[3]);
3075   operands[3] = const0_rtx;
3076   "
3079 (define_insn "aarch64_cstore<mode>"
3080   [(set (match_operand:ALLI 0 "register_operand" "=r")
3081         (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3082          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3083   ""
3084   "cset\\t%<w>0, %m1"
3085   [(set_attr "type" "csel")]
3088 ;; For a 24-bit immediate CST we can optimize the compare for equality
3089 ;; and branch sequence from:
3090 ;;      mov     x0, #imm1
3091 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
3092 ;;      cmp     x1, x0
3093 ;;      cset    x2, <ne,eq>
3094 ;; into the shorter:
3095 ;;      sub     x0, x1, #(CST & 0xfff000)
3096 ;;      subs    x0, x0, #(CST & 0x000fff)
3097 ;;      cset x2, <ne, eq>.
3098 (define_insn_and_split "*compare_cstore<mode>_insn"
3099   [(set (match_operand:GPI 0 "register_operand" "=r")
3100          (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3101                   (match_operand:GPI 2 "aarch64_imm24" "n")))]
3102   "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3103    && !aarch64_plus_operand (operands[2], <MODE>mode)
3104    && !reload_completed"
3105   "#"
3106   "&& true"
3107   [(const_int 0)]
3108   {
3109     HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3110     HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3111     rtx tmp = gen_reg_rtx (<MODE>mode);
3112     emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3113     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3114     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3115     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3116     emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3117     DONE;
3118   }
3119   [(set_attr "type" "csel")]
3122 ;; zero_extend version of the above
3123 (define_insn "*cstoresi_insn_uxtw"
3124   [(set (match_operand:DI 0 "register_operand" "=r")
3125         (zero_extend:DI
3126          (match_operator:SI 1 "aarch64_comparison_operator_mode"
3127           [(match_operand 2 "cc_register" "") (const_int 0)])))]
3128   ""
3129   "cset\\t%w0, %m1"
3130   [(set_attr "type" "csel")]
3133 (define_insn "cstore<mode>_neg"
3134   [(set (match_operand:ALLI 0 "register_operand" "=r")
3135         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3136                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
3137   ""
3138   "csetm\\t%<w>0, %m1"
3139   [(set_attr "type" "csel")]
3142 ;; zero_extend version of the above
3143 (define_insn "*cstoresi_neg_uxtw"
3144   [(set (match_operand:DI 0 "register_operand" "=r")
3145         (zero_extend:DI
3146          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3147                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3148   ""
3149   "csetm\\t%w0, %m1"
3150   [(set_attr "type" "csel")]
3153 (define_expand "cmov<mode>6"
3154   [(set (match_operand:GPI 0 "register_operand" "")
3155         (if_then_else:GPI
3156          (match_operator 1 "aarch64_comparison_operator"
3157           [(match_operand:GPI 2 "register_operand" "")
3158            (match_operand:GPI 3 "aarch64_plus_operand" "")])
3159          (match_operand:GPI 4 "register_operand" "")
3160          (match_operand:GPI 5 "register_operand" "")))]
3161   ""
3162   "
3163   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3164                                       operands[3]);
3165   operands[3] = const0_rtx;
3166   "
3169 (define_expand "cmov<mode>6"
3170   [(set (match_operand:GPF 0 "register_operand" "")
3171         (if_then_else:GPF
3172          (match_operator 1 "aarch64_comparison_operator"
3173           [(match_operand:GPF 2 "register_operand" "")
3174            (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3175          (match_operand:GPF 4 "register_operand" "")
3176          (match_operand:GPF 5 "register_operand" "")))]
3177   ""
3178   "
3179   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3180                                       operands[3]);
3181   operands[3] = const0_rtx;
3182   "
3185 (define_insn "*cmov<mode>_insn"
3186   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3187         (if_then_else:ALLI
3188          (match_operator 1 "aarch64_comparison_operator"
3189           [(match_operand 2 "cc_register" "") (const_int 0)])
3190          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3191          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3192   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3193      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3194   ;; Final two alternatives should be unreachable, but included for completeness
3195   "@
3196    csel\\t%<w>0, %<w>3, %<w>4, %m1
3197    csinv\\t%<w>0, %<w>3, <w>zr, %m1
3198    csinv\\t%<w>0, %<w>4, <w>zr, %M1
3199    csinc\\t%<w>0, %<w>3, <w>zr, %m1
3200    csinc\\t%<w>0, %<w>4, <w>zr, %M1
3201    mov\\t%<w>0, -1
3202    mov\\t%<w>0, 1"
3203   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3206 ;; zero_extend version of above
3207 (define_insn "*cmovsi_insn_uxtw"
3208   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3209         (zero_extend:DI
3210          (if_then_else:SI
3211           (match_operator 1 "aarch64_comparison_operator"
3212            [(match_operand 2 "cc_register" "") (const_int 0)])
3213           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3214           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3215   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3216      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3217   ;; Final two alternatives should be unreachable, but included for completeness
3218   "@
3219    csel\\t%w0, %w3, %w4, %m1
3220    csinv\\t%w0, %w3, wzr, %m1
3221    csinv\\t%w0, %w4, wzr, %M1
3222    csinc\\t%w0, %w3, wzr, %m1
3223    csinc\\t%w0, %w4, wzr, %M1
3224    mov\\t%w0, -1
3225    mov\\t%w0, 1"
3226   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3229 (define_insn "*cmovdi_insn_uxtw"
3230   [(set (match_operand:DI 0 "register_operand" "=r")
3231         (if_then_else:DI
3232          (match_operator 1 "aarch64_comparison_operator"
3233           [(match_operand 2 "cc_register" "") (const_int 0)])
3234          (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3235          (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3236   ""
3237   "csel\\t%w0, %w3, %w4, %m1"
3238   [(set_attr "type" "csel")]
3241 (define_insn "*cmov<mode>_insn"
3242   [(set (match_operand:GPF 0 "register_operand" "=w")
3243         (if_then_else:GPF
3244          (match_operator 1 "aarch64_comparison_operator"
3245           [(match_operand 2 "cc_register" "") (const_int 0)])
3246          (match_operand:GPF 3 "register_operand" "w")
3247          (match_operand:GPF 4 "register_operand" "w")))]
3248   "TARGET_FLOAT"
3249   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3250   [(set_attr "type" "fcsel")]
3253 (define_expand "mov<mode>cc"
3254   [(set (match_operand:ALLI 0 "register_operand" "")
3255         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3256                            (match_operand:ALLI 2 "register_operand" "")
3257                            (match_operand:ALLI 3 "register_operand" "")))]
3258   ""
3259   {
3260     rtx ccreg;
3261     enum rtx_code code = GET_CODE (operands[1]);
3263     if (code == UNEQ || code == LTGT)
3264       FAIL;
3266     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3267                                      XEXP (operands[1], 1));
3268     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3269   }
3272 (define_expand "mov<GPF:mode><GPI:mode>cc"
3273   [(set (match_operand:GPI 0 "register_operand" "")
3274         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3275                           (match_operand:GPF 2 "register_operand" "")
3276                           (match_operand:GPF 3 "register_operand" "")))]
3277   ""
3278   {
3279     rtx ccreg;
3280     enum rtx_code code = GET_CODE (operands[1]);
3282     if (code == UNEQ || code == LTGT)
3283       FAIL;
3285     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3286                                   XEXP (operands[1], 1));
3287     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3288   }
3291 (define_expand "mov<mode>cc"
3292   [(set (match_operand:GPF 0 "register_operand" "")
3293         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3294                           (match_operand:GPF 2 "register_operand" "")
3295                           (match_operand:GPF 3 "register_operand" "")))]
3296   ""
3297   {
3298     rtx ccreg;
3299     enum rtx_code code = GET_CODE (operands[1]);
3301     if (code == UNEQ || code == LTGT)
3302       FAIL;
3304     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3305                                   XEXP (operands[1], 1));
3306     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3307   }
3310 (define_expand "<neg_not_op><mode>cc"
3311   [(set (match_operand:GPI 0 "register_operand" "")
3312         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3313                           (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3314                           (match_operand:GPI 3 "register_operand" "")))]
3315   ""
3316   {
3317     rtx ccreg;
3318     enum rtx_code code = GET_CODE (operands[1]);
3320     if (code == UNEQ || code == LTGT)
3321       FAIL;
3323     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3324                                       XEXP (operands[1], 1));
3325     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3326   }
3329 ;; CRC32 instructions.
3330 (define_insn "aarch64_<crc_variant>"
3331   [(set (match_operand:SI 0 "register_operand" "=r")
3332         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3333                     (match_operand:<crc_mode> 2 "register_operand" "r")]
3334          CRC))]
3335   "TARGET_CRC32"
3336   {
3337     if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
3338       return "<crc_variant>\\t%w0, %w1, %x2";
3339     else
3340       return "<crc_variant>\\t%w0, %w1, %w2";
3341   }
3342   [(set_attr "type" "crc")]
3345 (define_insn "*csinc2<mode>_insn"
3346   [(set (match_operand:GPI 0 "register_operand" "=r")
3347         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3348                   (match_operand:GPI 1 "register_operand" "r")))]
3349   ""
3350   "cinc\\t%<w>0, %<w>1, %m2"
3351   [(set_attr "type" "csel")]
3354 (define_insn "csinc3<mode>_insn"
3355   [(set (match_operand:GPI 0 "register_operand" "=r")
3356         (if_then_else:GPI
3357           (match_operand 1 "aarch64_comparison_operation" "")
3358           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3359                     (const_int 1))
3360           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3361   ""
3362   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3363   [(set_attr "type" "csel")]
3366 (define_insn "*csinv3<mode>_insn"
3367   [(set (match_operand:GPI 0 "register_operand" "=r")
3368         (if_then_else:GPI
3369           (match_operand 1 "aarch64_comparison_operation" "")
3370           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3371           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3372   ""
3373   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3374   [(set_attr "type" "csel")]
3377 (define_insn "csneg3_uxtw_insn"
3378   [(set (match_operand:DI 0 "register_operand" "=r")
3379         (zero_extend:DI
3380           (if_then_else:SI
3381             (match_operand 1 "aarch64_comparison_operation" "")
3382             (neg:SI (match_operand:SI 2 "register_operand" "r"))
3383             (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3384   ""
3385   "csneg\\t%w0, %w3, %w2, %M1"
3386   [(set_attr "type" "csel")]
3389 (define_insn "csneg3<mode>_insn"
3390   [(set (match_operand:GPI 0 "register_operand" "=r")
3391         (if_then_else:GPI
3392           (match_operand 1 "aarch64_comparison_operation" "")
3393           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3394           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3395   ""
3396   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3397   [(set_attr "type" "csel")]
3400 ;; -------------------------------------------------------------------
3401 ;; Logical operations
3402 ;; -------------------------------------------------------------------
3405 (define_insn_and_split "*aarch64_and<mode>_imm2"
3406   [(set (match_operand:GPI 0 "register_operand" "=rk")
3407         (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3408                  (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3409   ""
3410   "#"
3411   "true"
3412   [(const_int 0)]
3413   {
3414      HOST_WIDE_INT val = INTVAL (operands[2]);
3415      rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3416      rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3418      emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3419      emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3420      DONE;
3421   }
3424 (define_insn "<optab><mode>3"
3425   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3426         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3427                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3428   ""
3429   "@
3430   <logical>\\t%<w>0, %<w>1, %<w>2
3431   <logical>\\t%<w>0, %<w>1, %2
3432   <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3433   [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3434    (set_attr "simd" "*,*,yes")]
3437 ;; zero_extend version of above
3438 (define_insn "*<optab>si3_uxtw"
3439   [(set (match_operand:DI 0 "register_operand" "=r,rk")
3440         (zero_extend:DI
3441          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3442                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3443   ""
3444   "@
3445    <logical>\\t%w0, %w1, %w2
3446    <logical>\\t%w0, %w1, %2"
3447   [(set_attr "type" "logic_reg,logic_imm")]
3450 (define_insn "*and<mode>3_compare0"
3451   [(set (reg:CC_NZ CC_REGNUM)
3452         (compare:CC_NZ
3453          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3454                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3455          (const_int 0)))
3456    (set (match_operand:GPI 0 "register_operand" "=r,r")
3457         (and:GPI (match_dup 1) (match_dup 2)))]
3458   ""
3459   "@
3460    ands\\t%<w>0, %<w>1, %<w>2
3461    ands\\t%<w>0, %<w>1, %2"
3462   [(set_attr "type" "logics_reg,logics_imm")]
3465 ;; zero_extend version of above
3466 (define_insn "*andsi3_compare0_uxtw"
3467   [(set (reg:CC_NZ CC_REGNUM)
3468         (compare:CC_NZ
3469          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3470                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3471          (const_int 0)))
3472    (set (match_operand:DI 0 "register_operand" "=r,r")
3473         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3474   ""
3475   "@
3476    ands\\t%w0, %w1, %w2
3477    ands\\t%w0, %w1, %2"
3478   [(set_attr "type" "logics_reg,logics_imm")]
3481 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3482   [(set (reg:CC_NZ CC_REGNUM)
3483         (compare:CC_NZ
3484          (and:GPI (SHIFT:GPI
3485                    (match_operand:GPI 1 "register_operand" "r")
3486                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3487                   (match_operand:GPI 3 "register_operand" "r"))
3488          (const_int 0)))
3489    (set (match_operand:GPI 0 "register_operand" "=r")
3490         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3491   ""
3492   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3493   [(set_attr "type" "logics_shift_imm")]
3496 ;; zero_extend version of above
3497 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3498   [(set (reg:CC_NZ CC_REGNUM)
3499         (compare:CC_NZ
3500          (and:SI (SHIFT:SI
3501                   (match_operand:SI 1 "register_operand" "r")
3502                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3503                  (match_operand:SI 3 "register_operand" "r"))
3504          (const_int 0)))
3505    (set (match_operand:DI 0 "register_operand" "=r")
3506         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3507                                 (match_dup 3))))]
3508   ""
3509   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3510   [(set_attr "type" "logics_shift_imm")]
3513 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3514   [(set (match_operand:GPI 0 "register_operand" "=r")
3515         (LOGICAL:GPI (SHIFT:GPI
3516                       (match_operand:GPI 1 "register_operand" "r")
3517                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3518                      (match_operand:GPI 3 "register_operand" "r")))]
3519   ""
3520   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3521   [(set_attr "type" "logic_shift_imm")]
3524 (define_insn "*<optab>_rol<mode>3"
3525   [(set (match_operand:GPI 0 "register_operand" "=r")
3526         (LOGICAL:GPI (rotate:GPI
3527                       (match_operand:GPI 1 "register_operand" "r")
3528                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3529                      (match_operand:GPI 3 "register_operand" "r")))]
3530   ""
3531   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3532   [(set_attr "type" "logic_shift_imm")]
3535 ;; zero_extend versions of above
3536 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3537   [(set (match_operand:DI 0 "register_operand" "=r")
3538         (zero_extend:DI
3539          (LOGICAL:SI (SHIFT:SI
3540                       (match_operand:SI 1 "register_operand" "r")
3541                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3542                      (match_operand:SI 3 "register_operand" "r"))))]
3543   ""
3544   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3545   [(set_attr "type" "logic_shift_imm")]
3548 (define_insn "*<optab>_rolsi3_uxtw"
3549   [(set (match_operand:DI 0 "register_operand" "=r")
3550         (zero_extend:DI
3551          (LOGICAL:SI (rotate:SI
3552                       (match_operand:SI 1 "register_operand" "r")
3553                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3554                      (match_operand:SI 3 "register_operand" "r"))))]
3555   ""
3556   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3557   [(set_attr "type" "logic_shift_imm")]
3560 (define_insn "one_cmpl<mode>2"
3561   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3562         (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3563   ""
3564   "@
3565   mvn\\t%<w>0, %<w>1
3566   mvn\\t%0.8b, %1.8b"
3567   [(set_attr "type" "logic_reg,neon_logic")
3568    (set_attr "simd" "*,yes")]
3571 (define_insn "*one_cmpl_<optab><mode>2"
3572   [(set (match_operand:GPI 0 "register_operand" "=r")
3573         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3574                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3575   ""
3576   "mvn\\t%<w>0, %<w>1, <shift> %2"
3577   [(set_attr "type" "logic_shift_imm")]
3580 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3582 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3583   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3584         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3585                      (match_operand:GPI 2 "register_operand" "r,w")))]
3586   ""
3587   "@
3588   <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3589   <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3590   [(set_attr "type" "logic_reg,neon_logic")
3591    (set_attr "simd" "*,yes")]
3594 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3595   [(set (match_operand:DI 0 "register_operand" "=r")
3596         (zero_extend:DI
3597           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3598                        (match_operand:SI 2 "register_operand" "r"))))]
3599   ""
3600   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3601   [(set_attr "type" "logic_reg")]
3604 (define_insn "*xor_one_cmplsidi3_ze"
3605   [(set (match_operand:DI 0 "register_operand" "=r")
3606         (zero_extend:DI
3607           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3608                           (match_operand:SI 2 "register_operand" "r")))))]
3609   ""
3610   "eon\\t%w0, %w1, %w2"
3611   [(set_attr "type" "logic_reg")]
3614 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3615 ;; eon does not operate on SIMD registers so the vector variant must be split.
3616 (define_insn_and_split "*xor_one_cmpl<mode>3"
3617   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3618         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3619                           (match_operand:GPI 2 "register_operand" "r,w"))))]
3620   ""
3621   "@
3622   eon\\t%<w>0, %<w>1, %<w>2
3623   #"
3624   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3625   [(set (match_operand:GPI 0 "register_operand" "=w")
3626         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3627                  (match_operand:GPI 2 "register_operand" "w")))
3628    (set (match_dup 0) (not:GPI (match_dup 0)))]
3629   ""
3630   [(set_attr "type" "logic_reg,multiple")
3631    (set_attr "simd" "*,yes")]
3634 (define_insn "*and_one_cmpl<mode>3_compare0"
3635   [(set (reg:CC_NZ CC_REGNUM)
3636         (compare:CC_NZ
3637          (and:GPI (not:GPI
3638                    (match_operand:GPI 1 "register_operand" "r"))
3639                   (match_operand:GPI 2 "register_operand" "r"))
3640          (const_int 0)))
3641    (set (match_operand:GPI 0 "register_operand" "=r")
3642         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3643   ""
3644   "bics\\t%<w>0, %<w>2, %<w>1"
3645   [(set_attr "type" "logics_reg")]
3648 ;; zero_extend version of above
3649 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3650   [(set (reg:CC_NZ CC_REGNUM)
3651         (compare:CC_NZ
3652          (and:SI (not:SI
3653                   (match_operand:SI 1 "register_operand" "r"))
3654                  (match_operand:SI 2 "register_operand" "r"))
3655          (const_int 0)))
3656    (set (match_operand:DI 0 "register_operand" "=r")
3657         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3658   ""
3659   "bics\\t%w0, %w2, %w1"
3660   [(set_attr "type" "logics_reg")]
3663 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3664   [(set (reg:CC_NZ CC_REGNUM)
3665     (compare:CC_NZ
3666      (and:GPI (not:GPI
3667            (match_operand:GPI 0 "register_operand" "r"))
3668           (match_operand:GPI 1 "register_operand" "r"))
3669      (const_int 0)))]
3670   ""
3671   "bics\\t<w>zr, %<w>1, %<w>0"
3672   [(set_attr "type" "logics_reg")]
3675 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3676   [(set (match_operand:GPI 0 "register_operand" "=r")
3677         (LOGICAL:GPI (not:GPI
3678                       (SHIFT:GPI
3679                        (match_operand:GPI 1 "register_operand" "r")
3680                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3681                      (match_operand:GPI 3 "register_operand" "r")))]
3682   ""
3683   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3684   [(set_attr "type" "logic_shift_imm")]
3687 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3688   [(set (match_operand:GPI 0 "register_operand" "=r")
3689         (not:GPI (xor:GPI
3690                       (SHIFT:GPI
3691                        (match_operand:GPI 1 "register_operand" "r")
3692                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3693                      (match_operand:GPI 3 "register_operand" "r"))))]
3694   ""
3695   "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3696   [(set_attr "type" "logic_shift_imm")]
3699 ;; Zero-extend version of the above.
3700 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3701   [(set (match_operand:DI 0 "register_operand" "=r")
3702         (zero_extend:DI
3703           (not:SI (xor:SI
3704                     (SHIFT:SI
3705                       (match_operand:SI 1 "register_operand" "r")
3706                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3707                     (match_operand:SI 3 "register_operand" "r")))))]
3708   ""
3709   "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3710   [(set_attr "type" "logic_shift_imm")]
3713 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3714   [(set (reg:CC_NZ CC_REGNUM)
3715         (compare:CC_NZ
3716          (and:GPI (not:GPI
3717                    (SHIFT:GPI
3718                     (match_operand:GPI 1 "register_operand" "r")
3719                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3720                   (match_operand:GPI 3 "register_operand" "r"))
3721          (const_int 0)))
3722    (set (match_operand:GPI 0 "register_operand" "=r")
3723         (and:GPI (not:GPI
3724                   (SHIFT:GPI
3725                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
3726   ""
3727   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3728   [(set_attr "type" "logics_shift_imm")]
3731 ;; zero_extend version of above
3732 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3733   [(set (reg:CC_NZ CC_REGNUM)
3734         (compare:CC_NZ
3735          (and:SI (not:SI
3736                   (SHIFT:SI
3737                    (match_operand:SI 1 "register_operand" "r")
3738                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3739                  (match_operand:SI 3 "register_operand" "r"))
3740          (const_int 0)))
3741    (set (match_operand:DI 0 "register_operand" "=r")
3742         (zero_extend:DI (and:SI
3743                          (not:SI
3744                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3745   ""
3746   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3747   [(set_attr "type" "logics_shift_imm")]
3750 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3751   [(set (reg:CC_NZ CC_REGNUM)
3752     (compare:CC_NZ
3753      (and:GPI (not:GPI
3754            (SHIFT:GPI
3755             (match_operand:GPI 0 "register_operand" "r")
3756             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3757           (match_operand:GPI 2 "register_operand" "r"))
3758      (const_int 0)))]
3759   ""
3760   "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3761   [(set_attr "type" "logics_shift_imm")]
3764 (define_insn "clz<mode>2"
3765   [(set (match_operand:GPI 0 "register_operand" "=r")
3766         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3767   ""
3768   "clz\\t%<w>0, %<w>1"
3769   [(set_attr "type" "clz")]
3772 (define_expand "ffs<mode>2"
3773   [(match_operand:GPI 0 "register_operand")
3774    (match_operand:GPI 1 "register_operand")]
3775   ""
3776   {
3777     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3778     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3780     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3781     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3782     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3783     DONE;
3784   }
3787 (define_insn "clrsb<mode>2"
3788   [(set (match_operand:GPI 0 "register_operand" "=r")
3789         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3790   ""
3791   "cls\\t%<w>0, %<w>1"
3792   [(set_attr "type" "clz")]
3795 (define_insn "rbit<mode>2"
3796   [(set (match_operand:GPI 0 "register_operand" "=r")
3797         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3798   ""
3799   "rbit\\t%<w>0, %<w>1"
3800   [(set_attr "type" "rbit")]
3803 ;; Split after reload into RBIT + CLZ.  Since RBIT is represented as an UNSPEC
3804 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3805 ;; expression and split after reload to enable scheduling them apart if
3806 ;; needed.
3808 (define_insn_and_split "ctz<mode>2"
3809  [(set (match_operand:GPI           0 "register_operand" "=r")
3810        (ctz:GPI (match_operand:GPI  1 "register_operand" "r")))]
3811   ""
3812   "#"
3813   "reload_completed"
3814   [(const_int 0)]
3815   "
3816   emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3817   emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3818   DONE;
3821 (define_insn "*and<mode>_compare0"
3822   [(set (reg:CC_NZ CC_REGNUM)
3823         (compare:CC_NZ
3824          (match_operand:SHORT 0 "register_operand" "r")
3825          (const_int 0)))]
3826   ""
3827   "tst\\t%<w>0, <short_mask>"
3828   [(set_attr "type" "alus_imm")]
3831 (define_insn "*ands<mode>_compare0"
3832   [(set (reg:CC_NZ CC_REGNUM)
3833         (compare:CC_NZ
3834          (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
3835          (const_int 0)))
3836    (set (match_operand:GPI 0 "register_operand" "=r")
3837         (zero_extend:GPI (match_dup 1)))]
3838   ""
3839   "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
3840   [(set_attr "type" "alus_imm")]
3843 (define_insn "*and<mode>3nr_compare0"
3844   [(set (reg:CC_NZ CC_REGNUM)
3845         (compare:CC_NZ
3846          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3847                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3848          (const_int 0)))]
3849   ""
3850   "@
3851    tst\\t%<w>0, %<w>1
3852    tst\\t%<w>0, %1"
3853   [(set_attr "type" "logics_reg,logics_imm")]
3856 (define_insn "*and<mode>3nr_compare0_zextract"
3857   [(set (reg:CC_NZ CC_REGNUM)
3858         (compare:CC_NZ
3859          (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
3860                   (match_operand:GPI 1 "const_int_operand" "n")
3861                   (match_operand:GPI 2 "const_int_operand" "n"))
3862          (const_int 0)))]
3863   "INTVAL (operands[1]) > 0
3864    && ((INTVAL (operands[1]) + INTVAL (operands[2]))
3865         <= GET_MODE_BITSIZE (<MODE>mode))
3866    && aarch64_bitmask_imm (
3867         UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
3868                                                  operands[2])),
3869         <MODE>mode)"
3870   {
3871     operands[1]
3872       = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
3873     return "tst\\t%<w>0, %1";
3874   }
3875   [(set_attr "type" "logics_shift_imm")]
3878 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3879   [(set (reg:CC_NZ CC_REGNUM)
3880         (compare:CC_NZ
3881          (and:GPI (SHIFT:GPI
3882                    (match_operand:GPI 0 "register_operand" "r")
3883                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3884                   (match_operand:GPI 2 "register_operand" "r"))
3885         (const_int 0)))]
3886   ""
3887   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3888   [(set_attr "type" "logics_shift_imm")]
3891 ;; -------------------------------------------------------------------
3892 ;; Shifts
3893 ;; -------------------------------------------------------------------
3895 (define_expand "<optab><mode>3"
3896   [(set (match_operand:GPI 0 "register_operand")
3897         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3898                     (match_operand:QI 2 "nonmemory_operand")))]
3899   ""
3900   {
3901     if (CONST_INT_P (operands[2]))
3902       {
3903         operands[2] = GEN_INT (INTVAL (operands[2])
3904                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3906         if (operands[2] == const0_rtx)
3907           {
3908             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3909             DONE;
3910           }
3911       }
3912   }
3915 (define_expand "ashl<mode>3"
3916   [(set (match_operand:SHORT 0 "register_operand")
3917         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3918                       (match_operand:QI 2 "const_int_operand")))]
3919   ""
3920   {
3921     operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
3923     if (operands[2] == const0_rtx)
3924       {
3925         emit_insn (gen_mov<mode> (operands[0], operands[1]));
3926         DONE;
3927       }
3928   }
3931 (define_expand "rotr<mode>3"
3932   [(set (match_operand:GPI 0 "register_operand")
3933         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3934                       (match_operand:QI 2 "nonmemory_operand")))]
3935   ""
3936   {
3937     if (CONST_INT_P (operands[2]))
3938       {
3939         operands[2] = GEN_INT (INTVAL (operands[2])
3940                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3942         if (operands[2] == const0_rtx)
3943           {
3944             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3945             DONE;
3946           }
3947       }
3948   }
3951 (define_expand "rotl<mode>3"
3952   [(set (match_operand:GPI 0 "register_operand")
3953         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3954                       (match_operand:QI 2 "nonmemory_operand")))]
3955   ""
3956   {
3957     /* (SZ - cnt) % SZ == -cnt % SZ */
3958     if (CONST_INT_P (operands[2]))
3959       {
3960         operands[2] = GEN_INT ((-INTVAL (operands[2]))
3961                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3962         if (operands[2] == const0_rtx)
3963           {
3964             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3965             DONE;
3966           }
3967       }
3968     else
3969       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3970                                         NULL_RTX, 1);
3971   }
3974 ;; Logical left shift using SISD or Integer instruction
3975 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3976   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
3977         (ashift:GPI
3978           (match_operand:GPI 1 "register_operand" "r,r,w,w")
3979           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
3980   ""
3981   "@
3982    lsl\t%<w>0, %<w>1, %2
3983    lsl\t%<w>0, %<w>1, %<w>2
3984    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3985    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
3986   [(set_attr "simd" "no,no,yes,yes")
3987    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
3990 ;; Logical right shift using SISD or Integer instruction
3991 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3992   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
3993         (lshiftrt:GPI
3994          (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
3995          (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
3996   ""
3997   "@
3998    lsr\t%<w>0, %<w>1, %2
3999    lsr\t%<w>0, %<w>1, %<w>2
4000    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4001    #
4002    #"
4003   [(set_attr "simd" "no,no,yes,yes,yes")
4004    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4007 (define_split
4008   [(set (match_operand:DI 0 "aarch64_simd_register")
4009         (lshiftrt:DI
4010            (match_operand:DI 1 "aarch64_simd_register")
4011            (match_operand:QI 2 "aarch64_simd_register")))]
4012   "TARGET_SIMD && reload_completed"
4013   [(set (match_dup 3)
4014         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4015    (set (match_dup 0)
4016         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4017   {
4018     operands[3] = gen_lowpart (QImode, operands[0]);
4019   }
4022 (define_split
4023   [(set (match_operand:SI 0 "aarch64_simd_register")
4024         (lshiftrt:SI
4025            (match_operand:SI 1 "aarch64_simd_register")
4026            (match_operand:QI 2 "aarch64_simd_register")))]
4027   "TARGET_SIMD && reload_completed"
4028   [(set (match_dup 3)
4029         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4030    (set (match_dup 0)
4031         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4032   {
4033     operands[3] = gen_lowpart (QImode, operands[0]);
4034   }
4037 ;; Arithmetic right shift using SISD or Integer instruction
4038 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4039   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4040         (ashiftrt:GPI
4041           (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4042           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
4043   ""
4044   "@
4045    asr\t%<w>0, %<w>1, %2
4046    asr\t%<w>0, %<w>1, %<w>2
4047    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4048    #
4049    #"
4050   [(set_attr "simd" "no,no,yes,yes,yes")
4051    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4054 (define_split
4055   [(set (match_operand:DI 0 "aarch64_simd_register")
4056         (ashiftrt:DI
4057            (match_operand:DI 1 "aarch64_simd_register")
4058            (match_operand:QI 2 "aarch64_simd_register")))]
4059   "TARGET_SIMD && reload_completed"
4060   [(set (match_dup 3)
4061         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4062    (set (match_dup 0)
4063         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4065   operands[3] = gen_lowpart (QImode, operands[0]);
4069 (define_split
4070   [(set (match_operand:SI 0 "aarch64_simd_register")
4071         (ashiftrt:SI
4072            (match_operand:SI 1 "aarch64_simd_register")
4073            (match_operand:QI 2 "aarch64_simd_register")))]
4074   "TARGET_SIMD && reload_completed"
4075   [(set (match_dup 3)
4076         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4077    (set (match_dup 0)
4078         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4080   operands[3] = gen_lowpart (QImode, operands[0]);
4084 (define_insn "*aarch64_sisd_ushl"
4085   [(set (match_operand:DI 0 "register_operand" "=w")
4086         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4087                     (match_operand:QI 2 "register_operand" "w")]
4088                    UNSPEC_SISD_USHL))]
4089   "TARGET_SIMD"
4090   "ushl\t%d0, %d1, %d2"
4091   [(set_attr "simd" "yes")
4092    (set_attr "type" "neon_shift_reg")]
4095 (define_insn "*aarch64_ushl_2s"
4096   [(set (match_operand:SI 0 "register_operand" "=w")
4097         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4098                     (match_operand:QI 2 "register_operand" "w")]
4099                    UNSPEC_USHL_2S))]
4100   "TARGET_SIMD"
4101   "ushl\t%0.2s, %1.2s, %2.2s"
4102   [(set_attr "simd" "yes")
4103    (set_attr "type" "neon_shift_reg")]
4106 (define_insn "*aarch64_sisd_sshl"
4107   [(set (match_operand:DI 0 "register_operand" "=w")
4108         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4109                     (match_operand:QI 2 "register_operand" "w")]
4110                    UNSPEC_SISD_SSHL))]
4111   "TARGET_SIMD"
4112   "sshl\t%d0, %d1, %d2"
4113   [(set_attr "simd" "yes")
4114    (set_attr "type" "neon_shift_reg")]
4117 (define_insn "*aarch64_sshl_2s"
4118   [(set (match_operand:SI 0 "register_operand" "=w")
4119         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4120                     (match_operand:QI 2 "register_operand" "w")]
4121                    UNSPEC_SSHL_2S))]
4122   "TARGET_SIMD"
4123   "sshl\t%0.2s, %1.2s, %2.2s"
4124   [(set_attr "simd" "yes")
4125    (set_attr "type" "neon_shift_reg")]
4128 (define_insn "*aarch64_sisd_neg_qi"
4129   [(set (match_operand:QI 0 "register_operand" "=w")
4130         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4131                    UNSPEC_SISD_NEG))]
4132   "TARGET_SIMD"
4133   "neg\t%d0, %d1"
4134   [(set_attr "simd" "yes")
4135    (set_attr "type" "neon_neg")]
4138 ;; Rotate right
4139 (define_insn "*ror<mode>3_insn"
4140   [(set (match_operand:GPI 0 "register_operand" "=r,r")
4141      (rotatert:GPI
4142        (match_operand:GPI 1 "register_operand" "r,r")
4143        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4144   ""
4145   "@
4146    ror\\t%<w>0, %<w>1, %2
4147    ror\\t%<w>0, %<w>1, %<w>2"
4148   [(set_attr "type" "rotate_imm,shift_reg")]
4151 ;; zero_extend version of above
4152 (define_insn "*<optab>si3_insn_uxtw"
4153   [(set (match_operand:DI 0 "register_operand" "=r,r")
4154         (zero_extend:DI (SHIFT:SI
4155          (match_operand:SI 1 "register_operand" "r,r")
4156          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4157   ""
4158   "@
4159    <shift>\\t%w0, %w1, %2
4160    <shift>\\t%w0, %w1, %w2"
4161   [(set_attr "type" "bfx,shift_reg")]
4164 (define_insn "*<optab><mode>3_insn"
4165   [(set (match_operand:SHORT 0 "register_operand" "=r")
4166         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4167                       (match_operand 2 "const_int_operand" "n")))]
4168   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4170   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4171   return "<bfshift>\t%w0, %w1, %2, %3";
4173   [(set_attr "type" "bfx")]
4176 (define_insn "*extr<mode>5_insn"
4177   [(set (match_operand:GPI 0 "register_operand" "=r")
4178         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4179                              (match_operand 3 "const_int_operand" "n"))
4180                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4181                                (match_operand 4 "const_int_operand" "n"))))]
4182   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4183    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4184   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4185   [(set_attr "type" "rotate_imm")]
4188 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4189 ;; so we have to match both orderings.
4190 (define_insn "*extr<mode>5_insn_alt"
4191   [(set (match_operand:GPI 0 "register_operand" "=r")
4192         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4193                                 (match_operand 4 "const_int_operand" "n"))
4194                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4195                               (match_operand 3 "const_int_operand" "n"))))]
4196   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4197    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4198        == GET_MODE_BITSIZE (<MODE>mode))"
4199   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4200   [(set_attr "type" "rotate_imm")]
4203 ;; zero_extend version of the above
4204 (define_insn "*extrsi5_insn_uxtw"
4205   [(set (match_operand:DI 0 "register_operand" "=r")
4206         (zero_extend:DI
4207          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4208                             (match_operand 3 "const_int_operand" "n"))
4209                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4210                               (match_operand 4 "const_int_operand" "n")))))]
4211   "UINTVAL (operands[3]) < 32 &&
4212    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4213   "extr\\t%w0, %w1, %w2, %4"
4214   [(set_attr "type" "rotate_imm")]
4217 (define_insn "*extrsi5_insn_uxtw_alt"
4218   [(set (match_operand:DI 0 "register_operand" "=r")
4219         (zero_extend:DI
4220          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4221                                (match_operand 4 "const_int_operand" "n"))
4222                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
4223                             (match_operand 3 "const_int_operand" "n")))))]
4224   "UINTVAL (operands[3]) < 32 &&
4225    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4226   "extr\\t%w0, %w1, %w2, %4"
4227   [(set_attr "type" "rotate_imm")]
4230 (define_insn "*ror<mode>3_insn"
4231   [(set (match_operand:GPI 0 "register_operand" "=r")
4232         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4233                     (match_operand 2 "const_int_operand" "n")))]
4234   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4236   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4237   return "ror\\t%<w>0, %<w>1, %3";
4239   [(set_attr "type" "rotate_imm")]
4242 ;; zero_extend version of the above
4243 (define_insn "*rorsi3_insn_uxtw"
4244   [(set (match_operand:DI 0 "register_operand" "=r")
4245         (zero_extend:DI
4246          (rotate:SI (match_operand:SI 1 "register_operand" "r")
4247                     (match_operand 2 "const_int_operand" "n"))))]
4248   "UINTVAL (operands[2]) < 32"
4250   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4251   return "ror\\t%w0, %w1, %3";
4253   [(set_attr "type" "rotate_imm")]
4256 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4257   [(set (match_operand:GPI 0 "register_operand" "=r")
4258         (ANY_EXTEND:GPI
4259          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4260                        (match_operand 2 "const_int_operand" "n"))))]
4261   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4263   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4264   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4266   [(set_attr "type" "bfx")]
4269 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4270   [(set (match_operand:GPI 0 "register_operand" "=r")
4271         (zero_extend:GPI
4272          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4273                          (match_operand 2 "const_int_operand" "n"))))]
4274   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4276   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4277   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4279   [(set_attr "type" "bfx")]
4282 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4283   [(set (match_operand:GPI 0 "register_operand" "=r")
4284         (sign_extend:GPI
4285          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4286                          (match_operand 2 "const_int_operand" "n"))))]
4287   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4289   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4290   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4292   [(set_attr "type" "bfx")]
4295 ;; -------------------------------------------------------------------
4296 ;; Bitfields
4297 ;; -------------------------------------------------------------------
4299 (define_expand "<optab>"
4300   [(set (match_operand:DI 0 "register_operand" "=r")
4301         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4302                         (match_operand 2
4303                           "aarch64_simd_shift_imm_offset_di")
4304                         (match_operand 3 "aarch64_simd_shift_imm_di")))]
4305   ""
4306   {
4307     if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4308                    1, GET_MODE_BITSIZE (DImode) - 1))
4309      FAIL;
4310   }
4314 (define_insn "*<optab><mode>"
4315   [(set (match_operand:GPI 0 "register_operand" "=r")
4316         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4317                          (match_operand 2
4318                            "aarch64_simd_shift_imm_offset_<mode>" "n")
4319                          (match_operand 3
4320                            "aarch64_simd_shift_imm_<mode>" "n")))]
4321   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4322              1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4323   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4324   [(set_attr "type" "bfx")]
4327 ;; Bitfield Insert (insv)
4328 (define_expand "insv<mode>"
4329   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4330                           (match_operand 1 "const_int_operand")
4331                           (match_operand 2 "const_int_operand"))
4332         (match_operand:GPI 3 "general_operand"))]
4333   ""
4335   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4336   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4337   rtx value = operands[3];
4339   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4340     FAIL;
4342   if (CONST_INT_P (value))
4343     {
4344       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4346       /* Prefer AND/OR for inserting all zeros or all ones.  */
4347       if ((UINTVAL (value) & mask) == 0
4348            || (UINTVAL (value) & mask) == mask)
4349         FAIL;
4351       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
4352       if (width == 16 && (pos % 16) == 0)
4353         DONE;
4354     }
4355   operands[3] = force_reg (<MODE>mode, value);
4358 (define_insn "*insv_reg<mode>"
4359   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4360                           (match_operand 1 "const_int_operand" "n")
4361                           (match_operand 2 "const_int_operand" "n"))
4362         (match_operand:GPI 3 "register_operand" "r"))]
4363   "!(UINTVAL (operands[1]) == 0
4364      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4365          > GET_MODE_BITSIZE (<MODE>mode)))"
4366   "bfi\\t%<w>0, %<w>3, %2, %1"
4367   [(set_attr "type" "bfm")]
4370 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4371   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4372                           (match_operand 1 "const_int_operand" "n")
4373                           (match_operand 2 "const_int_operand" "n"))
4374         (zero_extend:GPI (match_operand:ALLX 3  "register_operand" "r")))]
4375   "UINTVAL (operands[1]) <= <ALLX:sizen>"
4376   "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4377   [(set_attr "type" "bfm")]
4380 (define_insn "*extr_insv_lower_reg<mode>"
4381   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4382                           (match_operand 1 "const_int_operand" "n")
4383                           (const_int 0))
4384         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4385                           (match_dup 1)
4386                           (match_operand 3 "const_int_operand" "n")))]
4387   "!(UINTVAL (operands[1]) == 0
4388      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4389          > GET_MODE_BITSIZE (<MODE>mode)))"
4390   "bfxil\\t%<w>0, %<w>2, %3, %1"
4391   [(set_attr "type" "bfm")]
4394 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4395   [(set (match_operand:GPI 0 "register_operand" "=r")
4396         (ashift:GPI (ANY_EXTEND:GPI
4397                      (match_operand:ALLX 1 "register_operand" "r"))
4398                     (match_operand 2 "const_int_operand" "n")))]
4399   "UINTVAL (operands[2]) < <GPI:sizen>"
4401   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4402               ? GEN_INT (<ALLX:sizen>)
4403               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4404   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4406   [(set_attr "type" "bfx")]
4409 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4411 (define_insn "*andim_ashift<mode>_bfiz"
4412   [(set (match_operand:GPI 0 "register_operand" "=r")
4413         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4414                              (match_operand 2 "const_int_operand" "n"))
4415                  (match_operand 3 "const_int_operand" "n")))]
4416   "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4417   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4418   [(set_attr "type" "bfx")]
4421 (define_insn "bswap<mode>2"
4422   [(set (match_operand:GPI 0 "register_operand" "=r")
4423         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4424   ""
4425   "rev\\t%<w>0, %<w>1"
4426   [(set_attr "type" "rev")]
4429 (define_insn "bswaphi2"
4430   [(set (match_operand:HI 0 "register_operand" "=r")
4431         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4432   ""
4433   "rev16\\t%w0, %w1"
4434   [(set_attr "type" "rev")]
4437 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4438 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4439 ;; each valid permutation.
4441 (define_insn "rev16<mode>2"
4442   [(set (match_operand:GPI 0 "register_operand" "=r")
4443         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4444                                       (const_int 8))
4445                           (match_operand:GPI 3 "const_int_operand" "n"))
4446                  (and:GPI (lshiftrt:GPI (match_dup 1)
4447                                         (const_int 8))
4448                           (match_operand:GPI 2 "const_int_operand" "n"))))]
4449   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4450    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4451   "rev16\\t%<w>0, %<w>1"
4452   [(set_attr "type" "rev")]
4455 (define_insn "rev16<mode>2_alt"
4456   [(set (match_operand:GPI 0 "register_operand" "=r")
4457         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4458                                         (const_int 8))
4459                           (match_operand:GPI 2 "const_int_operand" "n"))
4460                  (and:GPI (ashift:GPI (match_dup 1)
4461                                       (const_int 8))
4462                           (match_operand:GPI 3 "const_int_operand" "n"))))]
4463   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4464    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4465   "rev16\\t%<w>0, %<w>1"
4466   [(set_attr "type" "rev")]
4469 ;; zero_extend version of above
4470 (define_insn "*bswapsi2_uxtw"
4471   [(set (match_operand:DI 0 "register_operand" "=r")
4472         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4473   ""
4474   "rev\\t%w0, %w1"
4475   [(set_attr "type" "rev")]
4478 ;; -------------------------------------------------------------------
4479 ;; Floating-point intrinsics
4480 ;; -------------------------------------------------------------------
4482 ;; frint floating-point round to integral standard patterns.
4483 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4485 (define_insn "<frint_pattern><mode>2"
4486   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4487         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4488          FRINT))]
4489   "TARGET_FLOAT"
4490   "frint<frint_suffix>\\t%<s>0, %<s>1"
4491   [(set_attr "type" "f_rint<stype>")]
4494 ;; frcvt floating-point round to integer and convert standard patterns.
4495 ;; Expands to lbtrunc, lceil, lfloor, lround.
4496 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4497   [(set (match_operand:GPI 0 "register_operand" "=r")
4498         (FIXUORS:GPI
4499           (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4500            FCVT)))]
4501   "TARGET_FLOAT"
4502   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4503   [(set_attr "type" "f_cvtf2i")]
4506 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4507   [(set (match_operand:GPI 0 "register_operand" "=r")
4508         (FIXUORS:GPI
4509           (mult:GPF
4510             (match_operand:GPF 1 "register_operand" "w")
4511             (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4512   "TARGET_FLOAT
4513    && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4514                 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4515   {
4516     int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4517     char buf[64];
4518     snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4519     output_asm_insn (buf, operands);
4520     return "";
4521   }
4522   [(set_attr "type" "f_cvtf2i")]
4525 ;; fma - no throw
4527 (define_insn "fma<mode>4"
4528   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4529         (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4530                      (match_operand:GPF_F16 2 "register_operand" "w")
4531                      (match_operand:GPF_F16 3 "register_operand" "w")))]
4532   "TARGET_FLOAT"
4533   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4534   [(set_attr "type" "fmac<stype>")]
4537 (define_insn "fnma<mode>4"
4538   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4539         (fma:GPF_F16
4540           (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w"))
4541           (match_operand:GPF_F16 2 "register_operand" "w")
4542           (match_operand:GPF_F16 3 "register_operand" "w")))]
4543   "TARGET_FLOAT"
4544   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4545   [(set_attr "type" "fmac<stype>")]
4548 (define_insn "fms<mode>4"
4549   [(set (match_operand:GPF 0 "register_operand" "=w")
4550         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4551                  (match_operand:GPF 2 "register_operand" "w")
4552                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4553   "TARGET_FLOAT"
4554   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
4555   [(set_attr "type" "fmac<s>")]
4558 (define_insn "fnms<mode>4"
4559   [(set (match_operand:GPF 0 "register_operand" "=w")
4560         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4561                  (match_operand:GPF 2 "register_operand" "w")
4562                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
4563   "TARGET_FLOAT"
4564   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4565   [(set_attr "type" "fmac<s>")]
4568 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4569 (define_insn "*fnmadd<mode>4"
4570   [(set (match_operand:GPF 0 "register_operand" "=w")
4571         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
4572                           (match_operand:GPF 2 "register_operand" "w")
4573                           (match_operand:GPF 3 "register_operand" "w"))))]
4574   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
4575   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
4576   [(set_attr "type" "fmac<s>")]
4579 ;; -------------------------------------------------------------------
4580 ;; Floating-point conversions
4581 ;; -------------------------------------------------------------------
4583 (define_insn "extendsfdf2"
4584   [(set (match_operand:DF 0 "register_operand" "=w")
4585         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
4586   "TARGET_FLOAT"
4587   "fcvt\\t%d0, %s1"
4588   [(set_attr "type" "f_cvt")]
4591 (define_insn "extendhfsf2"
4592   [(set (match_operand:SF 0 "register_operand" "=w")
4593         (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
4594   "TARGET_FLOAT"
4595   "fcvt\\t%s0, %h1"
4596   [(set_attr "type" "f_cvt")]
4599 (define_insn "extendhfdf2"
4600   [(set (match_operand:DF 0 "register_operand" "=w")
4601         (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
4602   "TARGET_FLOAT"
4603   "fcvt\\t%d0, %h1"
4604   [(set_attr "type" "f_cvt")]
4607 (define_insn "truncdfsf2"
4608   [(set (match_operand:SF 0 "register_operand" "=w")
4609         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
4610   "TARGET_FLOAT"
4611   "fcvt\\t%s0, %d1"
4612   [(set_attr "type" "f_cvt")]
4615 (define_insn "truncsfhf2"
4616   [(set (match_operand:HF 0 "register_operand" "=w")
4617         (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
4618   "TARGET_FLOAT"
4619   "fcvt\\t%h0, %s1"
4620   [(set_attr "type" "f_cvt")]
4623 (define_insn "truncdfhf2"
4624   [(set (match_operand:HF 0 "register_operand" "=w")
4625         (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
4626   "TARGET_FLOAT"
4627   "fcvt\\t%h0, %d1"
4628   [(set_attr "type" "f_cvt")]
4631 (define_insn "<optab>_trunc<GPF_F16:mode><GPI:mode>2"
4632   [(set (match_operand:GPI 0 "register_operand" "=r")
4633         (FIXUORS:GPI (match_operand:GPF_F16 1 "register_operand" "w")))]
4634   "TARGET_FLOAT"
4635   "fcvtz<su>\t%<GPI:w>0, %<GPF_F16:s>1"
4636   [(set_attr "type" "f_cvtf2i")]
4639 (define_insn "<optab><fcvt_target><GPF:mode>2"
4640   [(set (match_operand:GPF 0 "register_operand" "=w,w")
4641         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4642   "TARGET_FLOAT"
4643   "@
4644    <su_optab>cvtf\t%<GPF:s>0, %<s>1
4645    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4646   [(set_attr "simd" "yes,no")
4647    (set_attr "fp" "no,yes")
4648    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4651 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4652   [(set (match_operand:GPF 0 "register_operand" "=w")
4653         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4654   "TARGET_FLOAT"
4655   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4656   [(set_attr "type" "f_cvti2f")]
4659 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
4660 ;; midend will arrange for an SImode conversion to HFmode to first go
4661 ;; through DFmode, then to HFmode.  But first it will try converting
4662 ;; to DImode then down, which would match our DImode pattern below and
4663 ;; give very poor code-generation.  So, we must provide our own emulation
4664 ;; of the mid-end logic.
4666 (define_insn "aarch64_fp16_<optab><mode>hf2"
4667   [(set (match_operand:HF 0 "register_operand" "=w")
4668         (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
4669   "TARGET_FP_F16INST"
4670   "<su_optab>cvtf\t%h0, %<w>1"
4671   [(set_attr "type" "f_cvti2f")]
4674 (define_expand "<optab>sihf2"
4675   [(set (match_operand:HF 0 "register_operand")
4676         (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
4677   "TARGET_FLOAT"
4679   if (TARGET_FP_F16INST)
4680     emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
4681   else
4682     {
4683       rtx convert_target = gen_reg_rtx (DFmode);
4684       emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
4685       emit_insn (gen_truncdfhf2 (operands[0], convert_target));
4686     }
4687   DONE;
4691 ;; For DImode there is no wide enough floating-point mode that we
4692 ;; can convert through natively (TFmode would work, but requires a library
4693 ;; call).  However, we know that any value >= 65504 will be rounded
4694 ;; to infinity on conversion.  This is well within the range of SImode, so
4695 ;; we can:
4696 ;;   Saturate to SImode.
4697 ;;   Convert from that to DFmode
4698 ;;   Convert from that to HFmode (phew!).
4699 ;; Note that the saturation to SImode requires the SIMD extensions.  If
4700 ;; we ever need to provide this pattern where the SIMD extensions are not
4701 ;; available, we would need a different approach.
4703 (define_expand "<optab>dihf2"
4704   [(set (match_operand:HF 0 "register_operand")
4705         (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
4706   "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
4708   if (TARGET_FP_F16INST)
4709     emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
4710   else
4711     {
4712       rtx sat_target = gen_reg_rtx (SImode);
4713       emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
4714       emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
4715     }
4717   DONE;
4721 ;; Convert between fixed-point and floating-point (scalar modes)
4723 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
4724   [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
4725         (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
4726                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4727          FCVT_F2FIXED))]
4728   ""
4729   "@
4730    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
4731    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
4732   [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
4733    (set_attr "fp" "yes, *")
4734    (set_attr "simd" "*, yes")]
4737 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
4738   [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
4739         (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
4740                                    (match_operand:SI 2 "immediate_operand" "i, i")]
4741          FCVT_FIXED2F))]
4742   ""
4743   "@
4744    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
4745    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
4746   [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
4747    (set_attr "fp" "yes, *")
4748    (set_attr "simd" "*, yes")]
4751 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
4752   [(set (match_operand:GPI 0 "register_operand" "=r")
4753         (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
4754                      (match_operand:SI 2 "immediate_operand" "i")]
4755          FCVT_F2FIXED))]
4756   "TARGET_FP_F16INST"
4757    "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
4758   [(set_attr "type" "f_cvtf2i")]
4761 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
4762   [(set (match_operand:HF 0 "register_operand" "=w")
4763         (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
4764                     (match_operand:SI 2 "immediate_operand" "i")]
4765          FCVT_FIXED2F))]
4766   "TARGET_FP_F16INST"
4767   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
4768   [(set_attr "type" "f_cvti2f")]
4771 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
4772   [(set (match_operand:HI 0 "register_operand" "=w")
4773         (unspec:HI [(match_operand:HF 1 "register_operand" "w")
4774                     (match_operand:SI 2 "immediate_operand" "i")]
4775          FCVT_F2FIXED))]
4776   "TARGET_SIMD"
4777   "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
4778   [(set_attr "type" "neon_fp_to_int_s")]
4781 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
4782   [(set (match_operand:HF 0 "register_operand" "=w")
4783         (unspec:HF [(match_operand:HI 1 "register_operand" "w")
4784                     (match_operand:SI 2 "immediate_operand" "i")]
4785          FCVT_FIXED2F))]
4786   "TARGET_SIMD"
4787   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
4788   [(set_attr "type" "neon_int_to_fp_s")]
4791 ;; -------------------------------------------------------------------
4792 ;; Floating-point arithmetic
4793 ;; -------------------------------------------------------------------
4795 (define_insn "add<mode>3"
4796   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4797         (plus:GPF_F16
4798          (match_operand:GPF_F16 1 "register_operand" "w")
4799          (match_operand:GPF_F16 2 "register_operand" "w")))]
4800   "TARGET_FLOAT"
4801   "fadd\\t%<s>0, %<s>1, %<s>2"
4802   [(set_attr "type" "fadd<stype>")]
4805 (define_insn "sub<mode>3"
4806   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4807         (minus:GPF_F16
4808          (match_operand:GPF_F16 1 "register_operand" "w")
4809          (match_operand:GPF_F16 2 "register_operand" "w")))]
4810   "TARGET_FLOAT"
4811   "fsub\\t%<s>0, %<s>1, %<s>2"
4812   [(set_attr "type" "fadd<stype>")]
4815 (define_insn "mul<mode>3"
4816   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4817         (mult:GPF_F16
4818          (match_operand:GPF_F16 1 "register_operand" "w")
4819          (match_operand:GPF_F16 2 "register_operand" "w")))]
4820   "TARGET_FLOAT"
4821   "fmul\\t%<s>0, %<s>1, %<s>2"
4822   [(set_attr "type" "fmul<stype>")]
4825 (define_insn "*fnmul<mode>3"
4826   [(set (match_operand:GPF 0 "register_operand" "=w")
4827         (mult:GPF
4828                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4829                  (match_operand:GPF 2 "register_operand" "w")))]
4830   "TARGET_FLOAT && !flag_rounding_math"
4831   "fnmul\\t%<s>0, %<s>1, %<s>2"
4832   [(set_attr "type" "fmul<s>")]
4835 (define_insn "*fnmul<mode>3"
4836   [(set (match_operand:GPF 0 "register_operand" "=w")
4837         (neg:GPF (mult:GPF
4838                  (match_operand:GPF 1 "register_operand" "w")
4839                  (match_operand:GPF 2 "register_operand" "w"))))]
4840   "TARGET_FLOAT"
4841   "fnmul\\t%<s>0, %<s>1, %<s>2"
4842   [(set_attr "type" "fmul<s>")]
4845 (define_expand "div<mode>3"
4846  [(set (match_operand:GPF_F16 0 "register_operand")
4847        (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
4848                     (match_operand:GPF_F16 2 "register_operand")))]
4849  "TARGET_SIMD"
4851   if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
4852     DONE;
4854   operands[1] = force_reg (<MODE>mode, operands[1]);
4857 (define_insn "*div<mode>3"
4858   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4859         (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
4860                      (match_operand:GPF_F16 2 "register_operand" "w")))]
4861   "TARGET_FLOAT"
4862   "fdiv\\t%<s>0, %<s>1, %<s>2"
4863   [(set_attr "type" "fdiv<stype>")]
4866 (define_insn "neg<mode>2"
4867   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4868         (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4869   "TARGET_FLOAT"
4870   "fneg\\t%<s>0, %<s>1"
4871   [(set_attr "type" "ffarith<stype>")]
4874 (define_expand "sqrt<mode>2"
4875   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4876         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4877   "TARGET_FLOAT"
4879   if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
4880     DONE;
4883 (define_insn "*sqrt<mode>2"
4884   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4885         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4886   "TARGET_FLOAT"
4887   "fsqrt\\t%<s>0, %<s>1"
4888   [(set_attr "type" "fsqrt<stype>")]
4891 (define_insn "abs<mode>2"
4892   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4893         (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
4894   "TARGET_FLOAT"
4895   "fabs\\t%<s>0, %<s>1"
4896   [(set_attr "type" "ffarith<stype>")]
4899 ;; Given that smax/smin do not specify the result when either input is NaN,
4900 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4901 ;; for smin.
4903 (define_insn "smax<mode>3"
4904   [(set (match_operand:GPF 0 "register_operand" "=w")
4905         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4906                   (match_operand:GPF 2 "register_operand" "w")))]
4907   "TARGET_FLOAT"
4908   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4909   [(set_attr "type" "f_minmax<s>")]
4912 (define_insn "smin<mode>3"
4913   [(set (match_operand:GPF 0 "register_operand" "=w")
4914         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4915                   (match_operand:GPF 2 "register_operand" "w")))]
4916   "TARGET_FLOAT"
4917   "fminnm\\t%<s>0, %<s>1, %<s>2"
4918   [(set_attr "type" "f_minmax<s>")]
4921 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
4922 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
4923 ;; which implement the IEEE fmax ()/fmin () functions.
4924 (define_insn "<maxmin_uns><mode>3"
4925   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4926         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
4927                      (match_operand:GPF_F16 2 "register_operand" "w")]
4928                      FMAXMIN_UNS))]
4929   "TARGET_FLOAT"
4930   "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
4931   [(set_attr "type" "f_minmax<stype>")]
4934 ;; For copysign (x, y), we want to generate:
4936 ;;   LDR d2, #(1 << 63)
4937 ;;   BSL v2.8b, [y], [x]
4939 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
4940 ;; aarch64_simd_bsldf will select the best suited of these instructions
4941 ;; to generate based on register allocation, and knows how to partially
4942 ;; constant fold based on the values of X and Y, so expand through that.
4944 (define_expand "copysigndf3"
4945   [(match_operand:DF 0 "register_operand")
4946    (match_operand:DF 1 "register_operand")
4947    (match_operand:DF 2 "register_operand")]
4948   "TARGET_FLOAT && TARGET_SIMD"
4950   rtx mask = gen_reg_rtx (DImode);
4951   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
4952   emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
4953                                      operands[2], operands[1]));
4954   DONE;
4958 ;; As above, but we must first get to a 64-bit value if we wish to use
4959 ;; aarch64_simd_bslv2sf.
4961 (define_expand "copysignsf3"
4962   [(match_operand:SF 0 "register_operand")
4963    (match_operand:SF 1 "register_operand")
4964    (match_operand:SF 2 "register_operand")]
4965   "TARGET_FLOAT && TARGET_SIMD"
4967   rtx mask = gen_reg_rtx (DImode);
4969   /* Juggle modes to get us in to a vector mode for BSL.  */
4970   rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
4971   rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
4972   rtx tmp = gen_reg_rtx (V2SFmode);
4973   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
4974   emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
4975   emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
4976   DONE;
4980 ;; -------------------------------------------------------------------
4981 ;; Reload support
4982 ;; -------------------------------------------------------------------
4983 ;; Reload Scalar Floating point modes from constant pool.
4984 ;; The AArch64 port doesn't have __int128 constant move support.
4985 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
4986  [(set (match_operand:GPF_TF 0 "register_operand" "=w")
4987        (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
4988   (clobber (match_operand:P 2 "register_operand" "=&r"))]
4989  "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
4991    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
4992    emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
4993    DONE;
4997 ;; Reload Vector modes from constant pool.
4998 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
4999  [(set (match_operand:VALL 0 "register_operand" "=w")
5000        (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5001   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5002  "TARGET_FLOAT && aarch64_nopcrelative_literal_loads"
5004    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5005    emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5006    DONE;
5010 (define_expand "aarch64_reload_mov<mode>"
5011   [(set (match_operand:TX 0 "register_operand" "=w")
5012         (match_operand:TX 1 "register_operand" "w"))
5013    (clobber (match_operand:DI 2 "register_operand" "=&r"))
5014   ]
5015   "TARGET_FLOAT"
5016   {
5017     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5018     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5019     gen_aarch64_movtilow_tilow (op0, op1);
5020     gen_aarch64_movdi_tihigh (operands[2], op1);
5021     gen_aarch64_movtihigh_di (op0, operands[2]);
5022     DONE;
5023   }
5026 ;; The following secondary reload helpers patterns are invoked
5027 ;; after or during reload as we don't want these patterns to start
5028 ;; kicking in during the combiner.
5030 (define_insn "aarch64_movdi_<mode>low"
5031   [(set (match_operand:DI 0 "register_operand" "=r")
5032         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5033                          (const_int 64) (const_int 0)))]
5034   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5035   "fmov\\t%x0, %d1"
5036   [(set_attr "type" "f_mrc")
5037    (set_attr "length" "4")
5038   ])
5040 (define_insn "aarch64_movdi_<mode>high"
5041   [(set (match_operand:DI 0 "register_operand" "=r")
5042         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5043                          (const_int 64) (const_int 64)))]
5044   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5045   "fmov\\t%x0, %1.d[1]"
5046   [(set_attr "type" "f_mrc")
5047    (set_attr "length" "4")
5048   ])
5050 (define_insn "aarch64_mov<mode>high_di"
5051   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5052                          (const_int 64) (const_int 64))
5053         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5054   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5055   "fmov\\t%0.d[1], %x1"
5056   [(set_attr "type" "f_mcr")
5057    (set_attr "length" "4")
5058   ])
5060 (define_insn "aarch64_mov<mode>low_di"
5061   [(set (match_operand:TX 0 "register_operand" "=w")
5062         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5063   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5064   "fmov\\t%d0, %x1"
5065   [(set_attr "type" "f_mcr")
5066    (set_attr "length" "4")
5067   ])
5069 (define_insn "aarch64_movtilow_tilow"
5070   [(set (match_operand:TI 0 "register_operand" "=w")
5071         (zero_extend:TI
5072           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5073   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5074   "fmov\\t%d0, %d1"
5075   [(set_attr "type" "fmov")
5076    (set_attr "length" "4")
5077   ])
5079 ;; There is a deliberate reason why the parameters of high and lo_sum's
5080 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
5081 ;; and lo_sum's to be used with the labels defining the jump tables in
5082 ;; rodata section.
5084 (define_expand "add_losym"
5085   [(set (match_operand 0 "register_operand" "=r")
5086         (lo_sum (match_operand 1 "register_operand" "r")
5087                 (match_operand 2 "aarch64_valid_symref" "S")))]
5088   ""
5090   machine_mode mode = GET_MODE (operands[0]);
5092   emit_insn ((mode == DImode
5093               ? gen_add_losym_di
5094               : gen_add_losym_si) (operands[0],
5095                                    operands[1],
5096                                    operands[2]));
5097   DONE;
5100 (define_insn "add_losym_<mode>"
5101   [(set (match_operand:P 0 "register_operand" "=r")
5102         (lo_sum:P (match_operand:P 1 "register_operand" "r")
5103                   (match_operand 2 "aarch64_valid_symref" "S")))]
5104   ""
5105   "add\\t%<w>0, %<w>1, :lo12:%a2"
5106   [(set_attr "type" "alu_imm")]
5109 (define_insn "ldr_got_small_<mode>"
5110   [(set (match_operand:PTR 0 "register_operand" "=r")
5111         (unspec:PTR [(mem:PTR (lo_sum:PTR
5112                               (match_operand:PTR 1 "register_operand" "r")
5113                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5114                     UNSPEC_GOTSMALLPIC))]
5115   ""
5116   "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
5117   [(set_attr "type" "load1")]
5120 (define_insn "ldr_got_small_sidi"
5121   [(set (match_operand:DI 0 "register_operand" "=r")
5122         (zero_extend:DI
5123          (unspec:SI [(mem:SI (lo_sum:DI
5124                              (match_operand:DI 1 "register_operand" "r")
5125                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5126                     UNSPEC_GOTSMALLPIC)))]
5127   "TARGET_ILP32"
5128   "ldr\\t%w0, [%1, #:got_lo12:%a2]"
5129   [(set_attr "type" "load1")]
5132 (define_insn "ldr_got_small_28k_<mode>"
5133   [(set (match_operand:PTR 0 "register_operand" "=r")
5134         (unspec:PTR [(mem:PTR (lo_sum:PTR
5135                               (match_operand:PTR 1 "register_operand" "r")
5136                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5137                     UNSPEC_GOTSMALLPIC28K))]
5138   ""
5139   "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]"
5140   [(set_attr "type" "load1")]
5143 (define_insn "ldr_got_small_28k_sidi"
5144   [(set (match_operand:DI 0 "register_operand" "=r")
5145         (zero_extend:DI
5146          (unspec:SI [(mem:SI (lo_sum:DI
5147                              (match_operand:DI 1 "register_operand" "r")
5148                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5149                     UNSPEC_GOTSMALLPIC28K)))]
5150   "TARGET_ILP32"
5151   "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]"
5152   [(set_attr "type" "load1")]
5155 (define_insn "ldr_got_tiny"
5156   [(set (match_operand:DI 0 "register_operand" "=r")
5157         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5158                    UNSPEC_GOTTINYPIC))]
5159   ""
5160   "ldr\\t%0, %L1"
5161   [(set_attr "type" "load1")]
5164 (define_insn "aarch64_load_tp_hard"
5165   [(set (match_operand:DI 0 "register_operand" "=r")
5166         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5167   ""
5168   "mrs\\t%0, tpidr_el0"
5169   [(set_attr "type" "mrs")]
5172 ;; The TLS ABI specifically requires that the compiler does not schedule
5173 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5174 ;; Therefore we treat the stubs as an atomic sequence.
5175 (define_expand "tlsgd_small"
5176  [(parallel [(set (match_operand 0 "register_operand" "")
5177                   (call (mem:DI (match_dup 2)) (const_int 1)))
5178              (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5179              (clobber (reg:DI LR_REGNUM))])]
5180  ""
5182   operands[2] = aarch64_tls_get_addr ();
5185 (define_insn "*tlsgd_small"
5186   [(set (match_operand 0 "register_operand" "")
5187         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5188    (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5189    (clobber (reg:DI LR_REGNUM))
5190   ]
5191   ""
5192   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5193   [(set_attr "type" "call")
5194    (set_attr "length" "16")])
5196 (define_insn "tlsie_small_<mode>"
5197   [(set (match_operand:PTR 0 "register_operand" "=r")
5198         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5199                    UNSPEC_GOTSMALLTLS))]
5200   ""
5201   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5202   [(set_attr "type" "load1")
5203    (set_attr "length" "8")]
5206 (define_insn "tlsie_small_sidi"
5207   [(set (match_operand:DI 0 "register_operand" "=r")
5208         (zero_extend:DI
5209           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5210                       UNSPEC_GOTSMALLTLS)))]
5211   ""
5212   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5213   [(set_attr "type" "load1")
5214    (set_attr "length" "8")]
5217 (define_insn "tlsie_tiny_<mode>"
5218   [(set (match_operand:PTR 0 "register_operand" "=&r")
5219         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5220                      (match_operand:PTR 2 "register_operand" "r")]
5221                    UNSPEC_GOTTINYTLS))]
5222   ""
5223   "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5224   [(set_attr "type" "multiple")
5225    (set_attr "length" "8")]
5228 (define_insn "tlsie_tiny_sidi"
5229   [(set (match_operand:DI 0 "register_operand" "=&r")
5230         (zero_extend:DI
5231           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5232                       (match_operand:DI 2 "register_operand" "r")
5233                       ]
5234                       UNSPEC_GOTTINYTLS)))]
5235   ""
5236   "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5237   [(set_attr "type" "multiple")
5238    (set_attr "length" "8")]
5241 (define_insn "tlsle12_<mode>"
5242   [(set (match_operand:P 0 "register_operand" "=r")
5243         (unspec:P [(match_operand:P 1 "register_operand" "r")
5244                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5245                    UNSPEC_TLSLE12))]
5246   ""
5247   "add\\t%<w>0, %<w>1, #%L2";
5248   [(set_attr "type" "alu_sreg")
5249    (set_attr "length" "4")]
5252 (define_insn "tlsle24_<mode>"
5253   [(set (match_operand:P 0 "register_operand" "=r")
5254         (unspec:P [(match_operand:P 1 "register_operand" "r")
5255                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5256                    UNSPEC_TLSLE24))]
5257   ""
5258   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5259   [(set_attr "type" "multiple")
5260    (set_attr "length" "8")]
5263 (define_insn "tlsle32_<mode>"
5264   [(set (match_operand:P 0 "register_operand" "=r")
5265         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5266                    UNSPEC_TLSLE32))]
5267   ""
5268   "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5269   [(set_attr "type" "multiple")
5270    (set_attr "length" "8")]
5273 (define_insn "tlsle48_<mode>"
5274   [(set (match_operand:P 0 "register_operand" "=r")
5275         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5276                    UNSPEC_TLSLE48))]
5277   ""
5278   "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5279   [(set_attr "type" "multiple")
5280    (set_attr "length" "12")]
5283 (define_insn "tlsdesc_small_<mode>"
5284   [(set (reg:PTR R0_REGNUM)
5285         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5286                    UNSPEC_TLSDESC))
5287    (clobber (reg:DI LR_REGNUM))
5288    (clobber (reg:CC CC_REGNUM))
5289    (clobber (match_scratch:DI 1 "=r"))]
5290   "TARGET_TLS_DESC"
5291   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5292   [(set_attr "type" "call")
5293    (set_attr "length" "16")])
5295 (define_insn "stack_tie"
5296   [(set (mem:BLK (scratch))
5297         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5298                      (match_operand:DI 1 "register_operand" "rk")]
5299                     UNSPEC_PRLG_STK))]
5300   ""
5301   ""
5302   [(set_attr "length" "0")]
5305 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5306 ;; all of memory.  This blocks insns from being moved across this point.
5308 (define_insn "blockage"
5309   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5310   ""
5311   ""
5312   [(set_attr "length" "0")
5313    (set_attr "type" "block")]
5316 (define_insn "probe_stack_range_<PTR:mode>"
5317   [(set (match_operand:PTR 0 "register_operand" "=r")
5318         (unspec_volatile:PTR [(match_operand:PTR 1 "register_operand" "0")
5319                               (match_operand:PTR 2 "register_operand" "r")]
5320                                UNSPECV_PROBE_STACK_RANGE))]
5321   ""
5323   return aarch64_output_probe_stack_range (operands[0], operands[2]);
5325   [(set_attr "length" "32")]
5328 ;; Named pattern for expanding thread pointer reference.
5329 (define_expand "get_thread_pointerdi"
5330   [(match_operand:DI 0 "register_operand" "=r")]
5331   ""
5333   rtx tmp = aarch64_load_tp (operands[0]);
5334   if (tmp != operands[0])
5335     emit_move_insn (operands[0], tmp);
5336   DONE;
5339 ;; Named patterns for stack smashing protection.
5340 (define_expand "stack_protect_set"
5341   [(match_operand 0 "memory_operand")
5342    (match_operand 1 "memory_operand")]
5343   ""
5345   machine_mode mode = GET_MODE (operands[0]);
5347   emit_insn ((mode == DImode
5348               ? gen_stack_protect_set_di
5349               : gen_stack_protect_set_si) (operands[0], operands[1]));
5350   DONE;
5353 (define_insn "stack_protect_set_<mode>"
5354   [(set (match_operand:PTR 0 "memory_operand" "=m")
5355         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5356          UNSPEC_SP_SET))
5357    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5358   ""
5359   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5360   [(set_attr "length" "12")
5361    (set_attr "type" "multiple")])
5363 (define_expand "stack_protect_test"
5364   [(match_operand 0 "memory_operand")
5365    (match_operand 1 "memory_operand")
5366    (match_operand 2)]
5367   ""
5369   rtx result;
5370   machine_mode mode = GET_MODE (operands[0]);
5372   result = gen_reg_rtx(mode);
5374   emit_insn ((mode == DImode
5375               ? gen_stack_protect_test_di
5376               : gen_stack_protect_test_si) (result,
5377                                             operands[0],
5378                                             operands[1]));
5380   if (mode == DImode)
5381     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5382                                     result, const0_rtx, operands[2]));
5383   else
5384     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5385                                     result, const0_rtx, operands[2]));
5386   DONE;
5389 (define_insn "stack_protect_test_<mode>"
5390   [(set (match_operand:PTR 0 "register_operand" "=r")
5391         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5392                      (match_operand:PTR 2 "memory_operand" "m")]
5393          UNSPEC_SP_TEST))
5394    (clobber (match_scratch:PTR 3 "=&r"))]
5395   ""
5396   "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5397   [(set_attr "length" "12")
5398    (set_attr "type" "multiple")])
5400 ;; Write Floating-point Control Register.
5401 (define_insn "set_fpcr"
5402   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5403   ""
5404   "msr\\tfpcr, %0"
5405   [(set_attr "type" "mrs")])
5407 ;; Read Floating-point Control Register.
5408 (define_insn "get_fpcr"
5409   [(set (match_operand:SI 0 "register_operand" "=r")
5410         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
5411   ""
5412   "mrs\\t%0, fpcr"
5413   [(set_attr "type" "mrs")])
5415 ;; Write Floating-point Status Register.
5416 (define_insn "set_fpsr"
5417   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
5418   ""
5419   "msr\\tfpsr, %0"
5420   [(set_attr "type" "mrs")])
5422 ;; Read Floating-point Status Register.
5423 (define_insn "get_fpsr"
5424   [(set (match_operand:SI 0 "register_operand" "=r")
5425         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
5426   ""
5427   "mrs\\t%0, fpsr"
5428   [(set_attr "type" "mrs")])
5431 ;; Define the subtract-one-and-jump insns so loop.c
5432 ;; knows what to generate.
5433 (define_expand "doloop_end"
5434   [(use (match_operand 0 "" ""))      ; loop pseudo
5435    (use (match_operand 1 "" ""))]     ; label
5436   "optimize > 0 && flag_modulo_sched"
5438   rtx s0;
5439   rtx bcomp;
5440   rtx loc_ref;
5441   rtx cc_reg;
5442   rtx insn;
5443   rtx cmp;
5445   /* Currently SMS relies on the do-loop pattern to recognize loops
5446      where (1) the control part consists of all insns defining and/or
5447      using a certain 'count' register and (2) the loop count can be
5448      adjusted by modifying this register prior to the loop.
5449      ??? The possible introduction of a new block to initialize the
5450      new IV can potentially affect branch optimizations.  */
5452   if (GET_MODE (operands[0]) != DImode)
5453     FAIL;
5455   s0 = operands [0];
5456   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
5458   cmp = XVECEXP (PATTERN (insn), 0, 0);
5459   cc_reg = SET_DEST (cmp);
5460   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
5461   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
5462   emit_jump_insn (gen_rtx_SET (pc_rtx,
5463                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5464                                                      loc_ref, pc_rtx)));
5465   DONE;
5468 ;; AdvSIMD Stuff
5469 (include "aarch64-simd.md")
5471 ;; Atomic Operations
5472 (include "atomics.md")
5474 ;; ldp/stp peephole patterns
5475 (include "aarch64-ldpstp.md")