[AArch64] Simplify epilogue expansion using new helper functions.
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blob85bf2a7a5319ef3486927691c2f837859cbda4ca
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2014 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_FRECPE
79     UNSPEC_FRECPS
80     UNSPEC_FRECPX
81     UNSPEC_FRINTA
82     UNSPEC_FRINTI
83     UNSPEC_FRINTM
84     UNSPEC_FRINTN
85     UNSPEC_FRINTP
86     UNSPEC_FRINTX
87     UNSPEC_FRINTZ
88     UNSPEC_GOTSMALLPIC
89     UNSPEC_GOTSMALLTLS
90     UNSPEC_GOTTINYPIC
91     UNSPEC_LD1
92     UNSPEC_LD2
93     UNSPEC_LD3
94     UNSPEC_LD4
95     UNSPEC_MB
96     UNSPEC_NOP
97     UNSPEC_PRLG_STK
98     UNSPEC_RBIT
99     UNSPEC_SISD_NEG
100     UNSPEC_SISD_SSHL
101     UNSPEC_SISD_USHL
102     UNSPEC_SSHL_2S
103     UNSPEC_SSHR64
104     UNSPEC_ST1
105     UNSPEC_ST2
106     UNSPEC_ST3
107     UNSPEC_ST4
108     UNSPEC_ST2_LANE
109     UNSPEC_ST3_LANE
110     UNSPEC_ST4_LANE
111     UNSPEC_TLS
112     UNSPEC_TLSDESC
113     UNSPEC_USHL_2S
114     UNSPEC_USHR64
115     UNSPEC_VSTRUCTDUMMY
116     UNSPEC_SP_SET
117     UNSPEC_SP_TEST
120 (define_c_enum "unspecv" [
121     UNSPECV_EH_RETURN           ; Represent EH_RETURN
122     UNSPECV_GET_FPCR            ; Represent fetch of FPCR content.
123     UNSPECV_SET_FPCR            ; Represent assign of FPCR content.
124     UNSPECV_GET_FPSR            ; Represent fetch of FPSR content.
125     UNSPECV_SET_FPSR            ; Represent assign of FPSR content.
126   ]
129 ;; If further include files are added the defintion of MD_INCLUDES
130 ;; must be updated.
132 (include "constraints.md")
133 (include "predicates.md")
134 (include "iterators.md")
136 ;; -------------------------------------------------------------------
137 ;; Instruction types and attributes
138 ;; -------------------------------------------------------------------
140 ; The "type" attribute is is included here from AArch32 backend to be able
141 ; to share pipeline descriptions.
142 (include "../arm/types.md")
144 ;; Attribute that specifies whether or not the instruction touches fp
145 ;; registers.
146 (define_attr "fp" "no,yes" (const_string "no"))
148 ;; Attribute that specifies whether or not the instruction touches simd
149 ;; registers.
150 (define_attr "simd" "no,yes" (const_string "no"))
152 (define_attr "length" ""
153   (const_int 4))
155 ;; Attribute that controls whether an alternative is enabled or not.
156 ;; Currently it is only used to disable alternatives which touch fp or simd
157 ;; registers when -mgeneral-regs-only is specified.
158 (define_attr "enabled" "no,yes"
159   (cond [(ior
160         (and (eq_attr "fp" "yes")
161              (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
162         (and (eq_attr "simd" "yes")
163              (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
164              (const_string "no")
165         ] (const_string "yes")))
167 ;; -------------------------------------------------------------------
168 ;; Pipeline descriptions and scheduling
169 ;; -------------------------------------------------------------------
171 ;; Processor types.
172 (include "aarch64-tune.md")
174 ;; True if the generic scheduling description should be used.
176 (define_attr "generic_sched" "yes,no"
177   (const (if_then_else
178           (eq_attr "tune" "cortexa53,cortexa15")
179           (const_string "no")
180           (const_string "yes"))))
182 ;; Scheduling
183 (include "../arm/cortex-a53.md")
184 (include "../arm/cortex-a15.md")
186 ;; -------------------------------------------------------------------
187 ;; Jumps and other miscellaneous insns
188 ;; -------------------------------------------------------------------
190 (define_insn "indirect_jump"
191   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
192   ""
193   "br\\t%0"
194   [(set_attr "type" "branch")]
197 (define_insn "jump"
198   [(set (pc) (label_ref (match_operand 0 "" "")))]
199   ""
200   "b\\t%l0"
201   [(set_attr "type" "branch")]
204 (define_expand "cbranch<mode>4"
205   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
206                             [(match_operand:GPI 1 "register_operand" "")
207                              (match_operand:GPI 2 "aarch64_plus_operand" "")])
208                            (label_ref (match_operand 3 "" ""))
209                            (pc)))]
210   ""
211   "
212   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
213                                          operands[2]);
214   operands[2] = const0_rtx;
215   "
218 (define_expand "cbranch<mode>4"
219   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
220                             [(match_operand:GPF 1 "register_operand" "")
221                              (match_operand:GPF 2 "aarch64_reg_or_zero" "")])
222                            (label_ref (match_operand 3 "" ""))
223                            (pc)))]
224   ""
225   "
226   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
227                                          operands[2]);
228   operands[2] = const0_rtx;
229   "
232 (define_insn "*condjump"
233   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
234                             [(match_operand 1 "cc_register" "") (const_int 0)])
235                            (label_ref (match_operand 2 "" ""))
236                            (pc)))]
237   ""
238   "b%m0\\t%l2"
239   [(set_attr "type" "branch")]
242 (define_expand "casesi"
243   [(match_operand:SI 0 "register_operand" "")   ; Index
244    (match_operand:SI 1 "const_int_operand" "")  ; Lower bound
245    (match_operand:SI 2 "const_int_operand" "")  ; Total range
246    (match_operand:DI 3 "" "")                   ; Table label
247    (match_operand:DI 4 "" "")]                  ; Out of range label
248   ""
249   {
250     if (operands[1] != const0_rtx)
251       {
252         rtx reg = gen_reg_rtx (SImode);
254         /* Canonical RTL says that if you have:
256            (minus (X) (CONST))
258            then this should be emitted as:
260            (plus (X) (-CONST))
262            The use of trunc_int_for_mode ensures that the resulting
263            constant can be represented in SImode, this is important
264            for the corner case where operand[1] is INT_MIN.  */
266         operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
268         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
269               (operands[1], SImode))
270           operands[1] = force_reg (SImode, operands[1]);
271         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
272         operands[0] = reg;
273       }
275     if (!aarch64_plus_operand (operands[2], SImode))
276       operands[2] = force_reg (SImode, operands[2]);
277     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
278                                                  const0_rtx),
279                                     operands[0], operands[2], operands[4]));
281     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
282     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
283                                          operands[3]));
284     DONE;
285   }
288 (define_insn "casesi_dispatch"
289   [(parallel
290     [(set (pc)
291           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
292                            (match_operand:SI 1 "register_operand" "r")]
293                         UNSPEC_CASESI)))
294      (clobber (reg:CC CC_REGNUM))
295      (clobber (match_scratch:DI 3 "=r"))
296      (clobber (match_scratch:DI 4 "=r"))
297      (use (label_ref (match_operand 2 "" "")))])]
298   ""
299   "*
300   return aarch64_output_casesi (operands);
301   "
302   [(set_attr "length" "16")
303    (set_attr "type" "branch")]
306 (define_insn "nop"
307   [(unspec[(const_int 0)] UNSPEC_NOP)]
308   ""
309   "nop"
310   [(set_attr "type" "no_insn")]
313 (define_insn "trap"
314   [(trap_if (const_int 1) (const_int 8))]
315   ""
316   "brk #1000"
317   [(set_attr "type" "trap")])
319 (define_expand "prologue"
320   [(clobber (const_int 0))]
321   ""
322   "
323   aarch64_expand_prologue ();
324   DONE;
325   "
328 (define_expand "epilogue"
329   [(clobber (const_int 0))]
330   ""
331   "
332   aarch64_expand_epilogue (false);
333   DONE;
334   "
337 (define_expand "sibcall_epilogue"
338   [(clobber (const_int 0))]
339   ""
340   "
341   aarch64_expand_epilogue (true);
342   DONE;
343   "
346 (define_insn "*do_return"
347   [(return)]
348   ""
349   "ret"
350   [(set_attr "type" "branch")]
353 (define_insn "eh_return"
354   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
355     UNSPECV_EH_RETURN)]
356   ""
357   "#"
358   [(set_attr "type" "branch")]
362 (define_split
363   [(unspec_volatile [(match_operand:DI 0 "register_operand" "")]
364     UNSPECV_EH_RETURN)]
365   "reload_completed"
366   [(set (match_dup 1) (match_dup 0))]
367   {
368     operands[1] = aarch64_final_eh_return_addr ();
369   }
372 (define_insn "*cb<optab><mode>1"
373   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
374                                 (const_int 0))
375                            (label_ref (match_operand 1 "" ""))
376                            (pc)))]
377   ""
378   "<cbz>\\t%<w>0, %l1"
379   [(set_attr "type" "branch")]
383 (define_insn "*tb<optab><mode>1"
384   [(set (pc) (if_then_else
385               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
386                                     (const_int 1)
387                                     (match_operand 1 "const_int_operand" "n"))
388                    (const_int 0))
389              (label_ref (match_operand 2 "" ""))
390              (pc)))
391    (clobber (match_scratch:DI 3 "=r"))]
392   ""
393   "*
394   if (get_attr_length (insn) == 8)
395     return \"ubfx\\t%<w>3, %<w>0, %1, #1\;<cbz>\\t%<w>3, %l2\";
396   return \"<tbz>\\t%<w>0, %1, %l2\";
397   "
398   [(set_attr "type" "branch")
399    (set (attr "length")
400         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
401                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
402                       (const_int 4)
403                       (const_int 8)))]
406 (define_insn "*cb<optab><mode>1"
407   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
408                                  (const_int 0))
409                            (label_ref (match_operand 1 "" ""))
410                            (pc)))
411    (clobber (match_scratch:DI 2 "=r"))]
412   ""
413   "*
414   if (get_attr_length (insn) == 8)
415     return \"ubfx\\t%<w>2, %<w>0, <sizem1>, #1\;<cbz>\\t%<w>2, %l1\";
416   return \"<tbz>\\t%<w>0, <sizem1>, %l1\";
417   "
418   [(set_attr "type" "branch")
419    (set (attr "length")
420         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
421                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
422                       (const_int 4)
423                       (const_int 8)))]
426 ;; -------------------------------------------------------------------
427 ;; Subroutine calls and sibcalls
428 ;; -------------------------------------------------------------------
430 (define_expand "call_internal"
431   [(parallel [(call (match_operand 0 "memory_operand" "")
432                     (match_operand 1 "general_operand" ""))
433               (use (match_operand 2 "" ""))
434               (clobber (reg:DI LR_REGNUM))])])
436 (define_expand "call"
437   [(parallel [(call (match_operand 0 "memory_operand" "")
438                     (match_operand 1 "general_operand" ""))
439               (use (match_operand 2 "" ""))
440               (clobber (reg:DI LR_REGNUM))])]
441   ""
442   "
443   {
444     rtx callee, pat;
446     /* In an untyped call, we can get NULL for operand 2.  */
447     if (operands[2] == NULL)
448       operands[2] = const0_rtx;
450     /* Decide if we should generate indirect calls by loading the
451        64-bit address of the callee into a register before performing
452        the branch-and-link.  */
453     callee = XEXP (operands[0], 0);
454     if (GET_CODE (callee) == SYMBOL_REF
455         ? aarch64_is_long_call_p (callee)
456         : !REG_P (callee))
457       XEXP (operands[0], 0) = force_reg (Pmode, callee);
459     pat = gen_call_internal (operands[0], operands[1], operands[2]);
460     aarch64_emit_call_insn (pat);
461     DONE;
462   }"
465 (define_insn "*call_reg"
466   [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
467          (match_operand 1 "" ""))
468    (use (match_operand 2 "" ""))
469    (clobber (reg:DI LR_REGNUM))]
470   ""
471   "blr\\t%0"
472   [(set_attr "type" "call")]
475 (define_insn "*call_symbol"
476   [(call (mem:DI (match_operand:DI 0 "" ""))
477          (match_operand 1 "" ""))
478    (use (match_operand 2 "" ""))
479    (clobber (reg:DI LR_REGNUM))]
480   "GET_CODE (operands[0]) == SYMBOL_REF
481    && !aarch64_is_long_call_p (operands[0])"
482   "bl\\t%a0"
483   [(set_attr "type" "call")]
486 (define_expand "call_value_internal"
487   [(parallel [(set (match_operand 0 "" "")
488                    (call (match_operand 1 "memory_operand" "")
489                          (match_operand 2 "general_operand" "")))
490               (use (match_operand 3 "" ""))
491               (clobber (reg:DI LR_REGNUM))])])
493 (define_expand "call_value"
494   [(parallel [(set (match_operand 0 "" "")
495                    (call (match_operand 1 "memory_operand" "")
496                          (match_operand 2 "general_operand" "")))
497               (use (match_operand 3 "" ""))
498               (clobber (reg:DI LR_REGNUM))])]
499   ""
500   "
501   {
502     rtx callee, pat;
504     /* In an untyped call, we can get NULL for operand 3.  */
505     if (operands[3] == NULL)
506       operands[3] = const0_rtx;
508     /* Decide if we should generate indirect calls by loading the
509        64-bit address of the callee into a register before performing
510        the branch-and-link.  */
511     callee = XEXP (operands[1], 0);
512     if (GET_CODE (callee) == SYMBOL_REF
513         ? aarch64_is_long_call_p (callee)
514         : !REG_P (callee))
515       XEXP (operands[1], 0) = force_reg (Pmode, callee);
517     pat = gen_call_value_internal (operands[0], operands[1], operands[2],
518                                    operands[3]);
519     aarch64_emit_call_insn (pat);
520     DONE;
521   }"
524 (define_insn "*call_value_reg"
525   [(set (match_operand 0 "" "")
526         (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
527                       (match_operand 2 "" "")))
528    (use (match_operand 3 "" ""))
529    (clobber (reg:DI LR_REGNUM))]
530   ""
531   "blr\\t%1"
532   [(set_attr "type" "call")]
536 (define_insn "*call_value_symbol"
537   [(set (match_operand 0 "" "")
538         (call (mem:DI (match_operand:DI 1 "" ""))
539               (match_operand 2 "" "")))
540    (use (match_operand 3 "" ""))
541    (clobber (reg:DI LR_REGNUM))]
542   "GET_CODE (operands[1]) == SYMBOL_REF
543    && !aarch64_is_long_call_p (operands[1])"
544   "bl\\t%a1"
545   [(set_attr "type" "call")]
548 (define_expand "sibcall_internal"
549   [(parallel [(call (match_operand 0 "memory_operand" "")
550                     (match_operand 1 "general_operand" ""))
551               (return)
552               (use (match_operand 2 "" ""))])])
554 (define_expand "sibcall"
555   [(parallel [(call (match_operand 0 "memory_operand" "")
556                     (match_operand 1 "general_operand" ""))
557               (return)
558               (use (match_operand 2 "" ""))])]
559   ""
560   {
561     rtx pat;
563     if (!REG_P (XEXP (operands[0], 0))
564        && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF))
565      XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
567     if (operands[2] == NULL_RTX)
568       operands[2] = const0_rtx;
570     pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
571     aarch64_emit_call_insn (pat);
572     DONE;
573   }
576 (define_expand "sibcall_value_internal"
577   [(parallel [(set (match_operand 0 "" "")
578                    (call (match_operand 1 "memory_operand" "")
579                          (match_operand 2 "general_operand" "")))
580               (return)
581               (use (match_operand 3 "" ""))])])
583 (define_expand "sibcall_value"
584   [(parallel [(set (match_operand 0 "" "")
585                    (call (match_operand 1 "memory_operand" "")
586                          (match_operand 2 "general_operand" "")))
587               (return)
588               (use (match_operand 3 "" ""))])]
589   ""
590   {
591     rtx pat;
593     if (!REG_P (XEXP (operands[1], 0))
594        && (GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF))
595      XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
597     if (operands[3] == NULL_RTX)
598       operands[3] = const0_rtx;
600     pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
601                                       operands[3]);
602     aarch64_emit_call_insn (pat);
603     DONE;
604   }
607 (define_insn "*sibcall_insn"
608   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
609          (match_operand 1 "" ""))
610    (return)
611    (use (match_operand 2 "" ""))]
612   "SIBLING_CALL_P (insn)"
613   "@
614    br\\t%0
615    b\\t%a0"
616   [(set_attr "type" "branch, branch")]
619 (define_insn "*sibcall_value_insn"
620   [(set (match_operand 0 "" "")
621         (call (mem:DI (match_operand 1 "aarch64_call_insn_operand" "Ucs, Usf"))
622               (match_operand 2 "" "")))
623    (return)
624    (use (match_operand 3 "" ""))]
625   "SIBLING_CALL_P (insn)"
626   "@
627    br\\t%1
628    b\\t%a1"
629   [(set_attr "type" "branch, branch")]
632 ;; Call subroutine returning any type.
634 (define_expand "untyped_call"
635   [(parallel [(call (match_operand 0 "")
636                     (const_int 0))
637               (match_operand 1 "")
638               (match_operand 2 "")])]
639   ""
641   int i;
643   emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
645   for (i = 0; i < XVECLEN (operands[2], 0); i++)
646     {
647       rtx set = XVECEXP (operands[2], 0, i);
648       emit_move_insn (SET_DEST (set), SET_SRC (set));
649     }
651   /* The optimizer does not know that the call sets the function value
652      registers we stored in the result block.  We avoid problems by
653      claiming that all hard registers are used and clobbered at this
654      point.  */
655   emit_insn (gen_blockage ());
656   DONE;
659 ;; -------------------------------------------------------------------
660 ;; Moves
661 ;; -------------------------------------------------------------------
663 (define_expand "mov<mode>"
664   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
665         (match_operand:SHORT 1 "general_operand" ""))]
666   ""
667   "
668     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
669       operands[1] = force_reg (<MODE>mode, operands[1]);
670   "
673 (define_insn "*mov<mode>_aarch64"
674   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,   *w,r,*w, m, m, r,*w,*w")
675         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
676   "(register_operand (operands[0], <MODE>mode)
677     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
679    switch (which_alternative)
680      {
681      case 0:
682        return "mov\t%w0, %w1";
683      case 1:
684        return "mov\t%w0, %1";
685      case 2:
686        return aarch64_output_scalar_simd_mov_immediate (operands[1],
687                                                         <MODE>mode);
688      case 3:
689        return "ldr<size>\t%w0, %1";
690      case 4:
691        return "ldr\t%<size>0, %1";
692      case 5:
693        return "str<size>\t%w1, %0";
694      case 6:
695        return "str\t%<size>1, %0";
696      case 7:
697        return "umov\t%w0, %1.<v>[0]";
698      case 8:
699        return "dup\t%0.<Vallxd>, %w1";
700      case 9:
701        return "dup\t%<Vetype>0, %1.<v>[0]";
702      default:
703        gcc_unreachable ();
704      }
706   [(set_attr "type" "mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
707                      neon_from_gp<q>,neon_from_gp<q>, neon_dup")
708    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
711 (define_expand "mov<mode>"
712   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
713         (match_operand:GPI 1 "general_operand" ""))]
714   ""
715   "
716     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
717       operands[1] = force_reg (<MODE>mode, operands[1]);
719     if (CONSTANT_P (operands[1]))
720       {
721         aarch64_expand_mov_immediate (operands[0], operands[1]);
722         DONE;
723       }
724   "
727 (define_insn "*movsi_aarch64"
728   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,*w,m,  m,r,r  ,*w, r,*w")
729         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
730   "(register_operand (operands[0], SImode)
731     || aarch64_reg_or_zero (operands[1], SImode))"
732   "@
733    mov\\t%w0, %w1
734    mov\\t%w0, %w1
735    mov\\t%w0, %w1
736    mov\\t%w0, %1
737    ldr\\t%w0, %1
738    ldr\\t%s0, %1
739    str\\t%w1, %0
740    str\\t%s1, %0
741    adr\\t%x0, %a1
742    adrp\\t%x0, %A1
743    fmov\\t%s0, %w1
744    fmov\\t%w0, %s1
745    fmov\\t%s0, %s1"
746   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,load1,load1,store1,store1,\
747                      adr,adr,f_mcr,f_mrc,fmov")
748    (set_attr "fp" "*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
751 (define_insn "*movdi_aarch64"
752   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,*w,m,  m,r,r,  *w, r,*w,w")
753         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
754   "(register_operand (operands[0], DImode)
755     || aarch64_reg_or_zero (operands[1], DImode))"
756   "@
757    mov\\t%x0, %x1
758    mov\\t%0, %x1
759    mov\\t%x0, %1
760    mov\\t%x0, %1
761    ldr\\t%x0, %1
762    ldr\\t%d0, %1
763    str\\t%x1, %0
764    str\\t%d1, %0
765    adr\\t%x0, %a1
766    adrp\\t%x0, %A1
767    fmov\\t%d0, %x1
768    fmov\\t%x0, %d1
769    fmov\\t%d0, %d1
770    movi\\t%d0, %1"
771   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,load1,load1,store1,store1,\
772                      adr,adr,f_mcr,f_mrc,fmov,fmov")
773    (set_attr "fp" "*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
774    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
777 (define_insn "insv_imm<mode>"
778   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
779                           (const_int 16)
780                           (match_operand:GPI 1 "const_int_operand" "n"))
781         (match_operand:GPI 2 "const_int_operand" "n"))]
782   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
783    && UINTVAL (operands[1]) % 16 == 0"
784   "movk\\t%<w>0, %X2, lsl %1"
785   [(set_attr "type" "mov_imm")]
788 (define_expand "movti"
789   [(set (match_operand:TI 0 "nonimmediate_operand" "")
790         (match_operand:TI 1 "general_operand" ""))]
791   ""
792   "
793     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
794       operands[1] = force_reg (TImode, operands[1]);
795   "
798 (define_insn "*movti_aarch64"
799   [(set (match_operand:TI 0
800          "nonimmediate_operand"  "=r, *w,r ,*w,r  ,Ump,Ump,*w,m")
801         (match_operand:TI 1
802          "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r  ,Z  , m,*w"))]
803   "(register_operand (operands[0], TImode)
804     || aarch64_reg_or_zero (operands[1], TImode))"
805   "@
806    #
807    #
808    #
809    orr\\t%0.16b, %1.16b, %1.16b
810    ldp\\t%0, %H0, %1
811    stp\\t%1, %H1, %0
812    stp\\txzr, xzr, %0
813    ldr\\t%q0, %1
814    str\\t%q1, %0"
815   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
816                              load2,store2,store2,f_loadd,f_stored")
817    (set_attr "length" "8,8,8,4,4,4,4,4,4")
818    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
819    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
822 ;; Split a TImode register-register or register-immediate move into
823 ;; its component DImode pieces, taking care to handle overlapping
824 ;; source and dest registers.
825 (define_split
826    [(set (match_operand:TI 0 "register_operand" "")
827          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
828   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
829   [(const_int 0)]
831   aarch64_split_128bit_move (operands[0], operands[1]);
832   DONE;
835 (define_expand "mov<mode>"
836   [(set (match_operand:GPF 0 "nonimmediate_operand" "")
837         (match_operand:GPF 1 "general_operand" ""))]
838   ""
839   "
840     if (!TARGET_FLOAT)
841      {
842         sorry (\"%qs and floating point code\", \"-mgeneral-regs-only\");
843         FAIL;
844      }
846     if (GET_CODE (operands[0]) == MEM)
847       operands[1] = force_reg (<MODE>mode, operands[1]);
848   "
851 (define_insn "*movsf_aarch64"
852   [(set (match_operand:SF 0 "nonimmediate_operand" "=w, ?r,w,w  ,w,m,r,m ,r")
853         (match_operand:SF 1 "general_operand"      "?rY, w,w,Ufc,m,w,m,rY,r"))]
854   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
855     || register_operand (operands[1], SFmode))"
856   "@
857    fmov\\t%s0, %w1
858    fmov\\t%w0, %s1
859    fmov\\t%s0, %s1
860    fmov\\t%s0, %1
861    ldr\\t%s0, %1
862    str\\t%s1, %0
863    ldr\\t%w0, %1
864    str\\t%w1, %0
865    mov\\t%w0, %w1"
866   [(set_attr "type" "f_mcr,f_mrc,fmov,fconsts,\
867                      f_loads,f_stores,f_loads,f_stores,mov_reg")]
870 (define_insn "*movdf_aarch64"
871   [(set (match_operand:DF 0 "nonimmediate_operand" "=w, ?r,w,w  ,w,m,r,m ,r")
872         (match_operand:DF 1 "general_operand"      "?rY, w,w,Ufc,m,w,m,rY,r"))]
873   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
874     || register_operand (operands[1], DFmode))"
875   "@
876    fmov\\t%d0, %x1
877    fmov\\t%x0, %d1
878    fmov\\t%d0, %d1
879    fmov\\t%d0, %1
880    ldr\\t%d0, %1
881    str\\t%d1, %0
882    ldr\\t%x0, %1
883    str\\t%x1, %0
884    mov\\t%x0, %x1"
885   [(set_attr "type" "f_mcr,f_mrc,fmov,fconstd,\
886                      f_loadd,f_stored,f_loadd,f_stored,mov_reg")]
889 (define_expand "movtf"
890   [(set (match_operand:TF 0 "nonimmediate_operand" "")
891         (match_operand:TF 1 "general_operand" ""))]
892   ""
893   "
894     if (!TARGET_FLOAT)
895      {
896         sorry (\"%qs and floating point code\", \"-mgeneral-regs-only\");
897         FAIL;
898      }
900     if (GET_CODE (operands[0]) == MEM)
901       operands[1] = force_reg (TFmode, operands[1]);
902   "
905 (define_insn "*movtf_aarch64"
906   [(set (match_operand:TF 0
907          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump")
908         (match_operand:TF 1
909          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,Ump,?rY"))]
910   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
911     || register_operand (operands[1], TFmode))"
912   "@
913    orr\\t%0.16b, %1.16b, %1.16b
914    #
915    #
916    #
917    movi\\t%0.2d, #0
918    fmov\\t%s0, wzr
919    ldr\\t%q0, %1
920    str\\t%q1, %0
921    ldp\\t%0, %H0, %1
922    stp\\t%1, %H1, %0"
923   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,fconstd,fconstd,\
924                      f_loadd,f_stored,neon_load1_2reg,neon_store1_2reg")
925    (set_attr "length" "4,8,8,8,4,4,4,4,4,4")
926    (set_attr "fp" "*,*,yes,yes,*,yes,yes,yes,*,*")
927    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*")]
930 (define_split
931    [(set (match_operand:TF 0 "register_operand" "")
932          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
933   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
934   [(const_int 0)]
935   {
936     aarch64_split_128bit_move (operands[0], operands[1]);
937     DONE;
938   }
941 ;; 0 is dst
942 ;; 1 is src
943 ;; 2 is size of move in bytes
944 ;; 3 is alignment
946 (define_expand "movmemdi"
947   [(match_operand:BLK 0 "memory_operand")
948    (match_operand:BLK 1 "memory_operand")
949    (match_operand:DI 2 "immediate_operand")
950    (match_operand:DI 3 "immediate_operand")]
951    "!STRICT_ALIGNMENT"
953   if (aarch64_expand_movmem (operands))
954     DONE;
955   FAIL;
959 ;; Operands 1 and 3 are tied together by the final condition; so we allow
960 ;; fairly lax checking on the second memory operation.
961 (define_insn "load_pair<mode>"
962   [(set (match_operand:GPI 0 "register_operand" "=r")
963         (match_operand:GPI 1 "aarch64_mem_pair_operand" "Ump"))
964    (set (match_operand:GPI 2 "register_operand" "=r")
965         (match_operand:GPI 3 "memory_operand" "m"))]
966   "rtx_equal_p (XEXP (operands[3], 0),
967                 plus_constant (Pmode,
968                                XEXP (operands[1], 0),
969                                GET_MODE_SIZE (<MODE>mode)))"
970   "ldp\\t%<w>0, %<w>2, %1"
971   [(set_attr "type" "load2")]
974 ;; Operands 0 and 2 are tied together by the final condition; so we allow
975 ;; fairly lax checking on the second memory operation.
976 (define_insn "store_pair<mode>"
977   [(set (match_operand:GPI 0 "aarch64_mem_pair_operand" "=Ump")
978         (match_operand:GPI 1 "register_operand" "r"))
979    (set (match_operand:GPI 2 "memory_operand" "=m")
980         (match_operand:GPI 3 "register_operand" "r"))]
981   "rtx_equal_p (XEXP (operands[2], 0),
982                 plus_constant (Pmode,
983                                XEXP (operands[0], 0),
984                                GET_MODE_SIZE (<MODE>mode)))"
985   "stp\\t%<w>1, %<w>3, %0"
986   [(set_attr "type" "store2")]
989 ;; Operands 1 and 3 are tied together by the final condition; so we allow
990 ;; fairly lax checking on the second memory operation.
991 (define_insn "load_pair<mode>"
992   [(set (match_operand:GPF 0 "register_operand" "=w")
993         (match_operand:GPF 1 "aarch64_mem_pair_operand" "Ump"))
994    (set (match_operand:GPF 2 "register_operand" "=w")
995         (match_operand:GPF 3 "memory_operand" "m"))]
996   "rtx_equal_p (XEXP (operands[3], 0),
997                 plus_constant (Pmode,
998                                XEXP (operands[1], 0),
999                                GET_MODE_SIZE (<MODE>mode)))"
1000   "ldp\\t%<w>0, %<w>2, %1"
1001   [(set_attr "type" "neon_load1_2reg<q>")]
1004 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1005 ;; fairly lax checking on the second memory operation.
1006 (define_insn "store_pair<mode>"
1007   [(set (match_operand:GPF 0 "aarch64_mem_pair_operand" "=Ump")
1008         (match_operand:GPF 1 "register_operand" "w"))
1009    (set (match_operand:GPF 2 "memory_operand" "=m")
1010         (match_operand:GPF 3 "register_operand" "w"))]
1011   "rtx_equal_p (XEXP (operands[2], 0),
1012                 plus_constant (Pmode,
1013                                XEXP (operands[0], 0),
1014                                GET_MODE_SIZE (<MODE>mode)))"
1015   "stp\\t%<w>1, %<w>3, %0"
1016   [(set_attr "type" "neon_store1_2reg<q>")]
1019 ;; Load pair with writeback.  This is primarily used in function epilogues
1020 ;; when restoring [fp,lr]
1021 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1022   [(parallel
1023     [(set (match_operand:P 0 "register_operand" "=k")
1024           (plus:P (match_operand:P 1 "register_operand" "0")
1025                   (match_operand:P 4 "const_int_operand" "n")))
1026      (set (match_operand:GPI 2 "register_operand" "=r")
1027           (mem:GPI (plus:P (match_dup 1)
1028                    (match_dup 4))))
1029      (set (match_operand:GPI 3 "register_operand" "=r")
1030           (mem:GPI (plus:P (match_dup 1)
1031                    (match_operand:P 5 "const_int_operand" "n"))))])]
1032   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1033   "ldp\\t%<w>2, %<w>3, [%1], %4"
1034   [(set_attr "type" "load2")]
1037 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1038   [(parallel
1039     [(set (match_operand:P 0 "register_operand" "=k")
1040           (plus:P (match_operand:P 1 "register_operand" "0")
1041                   (match_operand:P 4 "const_int_operand" "n")))
1042      (set (match_operand:GPF 2 "register_operand" "=w")
1043           (mem:GPF (plus:P (match_dup 1)
1044                    (match_dup 4))))
1045      (set (match_operand:GPF 3 "register_operand" "=w")
1046           (mem:GPF (plus:P (match_dup 1)
1047                    (match_operand:P 5 "const_int_operand" "n"))))])]
1048   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1049   "ldp\\t%<w>2, %<w>3, [%1], %4"
1050   [(set_attr "type" "neon_load1_2reg")]
1053 ;; Store pair with writeback.  This is primarily used in function prologues
1054 ;; when saving [fp,lr]
1055 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1056   [(parallel
1057     [(set (match_operand:P 0 "register_operand" "=&k")
1058           (plus:P (match_operand:P 1 "register_operand" "0")
1059                   (match_operand:P 4 "const_int_operand" "n")))
1060      (set (mem:GPI (plus:P (match_dup 0)
1061                    (match_dup 4)))
1062           (match_operand:GPI 2 "register_operand" "r"))
1063      (set (mem:GPI (plus:P (match_dup 0)
1064                    (match_operand:P 5 "const_int_operand" "n")))
1065           (match_operand:GPI 3 "register_operand" "r"))])]
1066   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1067   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1068   [(set_attr "type" "store2")]
1071 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1072   [(parallel
1073     [(set (match_operand:P 0 "register_operand" "=&k")
1074           (plus:P (match_operand:P 1 "register_operand" "0")
1075                   (match_operand:P 4 "const_int_operand" "n")))
1076      (set (mem:GPF (plus:P (match_dup 0)
1077                    (match_dup 4)))
1078           (match_operand:GPF 2 "register_operand" "w"))
1079      (set (mem:GPF (plus:P (match_dup 0)
1080                    (match_operand:P 5 "const_int_operand" "n")))
1081           (match_operand:GPF 3 "register_operand" "w"))])]
1082   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1083   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1084   [(set_attr "type" "neon_store1_2reg<q>")]
1087 ;; -------------------------------------------------------------------
1088 ;; Sign/Zero extension
1089 ;; -------------------------------------------------------------------
1091 (define_expand "<optab>sidi2"
1092   [(set (match_operand:DI 0 "register_operand")
1093         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1094   ""
1097 (define_insn "*extendsidi2_aarch64"
1098   [(set (match_operand:DI 0 "register_operand" "=r,r")
1099         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1100   ""
1101   "@
1102    sxtw\t%0, %w1
1103    ldrsw\t%0, %1"
1104   [(set_attr "type" "extend,load1")]
1107 (define_insn "*zero_extendsidi2_aarch64"
1108   [(set (match_operand:DI 0 "register_operand" "=r,r")
1109         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1110   ""
1111   "@
1112    uxtw\t%0, %w1
1113    ldr\t%w0, %1"
1114   [(set_attr "type" "extend,load1")]
1117 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1118   [(set (match_operand:GPI 0 "register_operand")
1119         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1120   ""
1123 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1124   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1125         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1126   ""
1127   "@
1128    sxt<SHORT:size>\t%<GPI:w>0, %w1
1129    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1130   [(set_attr "type" "extend,load1")]
1133 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1134   [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1135         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1136   ""
1137   "@
1138    uxt<SHORT:size>\t%<GPI:w>0, %w1
1139    ldr<SHORT:size>\t%w0, %1
1140    ldr\t%<SHORT:size>0, %1"
1141   [(set_attr "type" "extend,load1,load1")]
1144 (define_expand "<optab>qihi2"
1145   [(set (match_operand:HI 0 "register_operand")
1146         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1147   ""
1150 (define_insn "*<optab>qihi2_aarch64"
1151   [(set (match_operand:HI 0 "register_operand" "=r,r")
1152         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1153   ""
1154   "@
1155    <su>xtb\t%w0, %w1
1156    <ldrxt>b\t%w0, %1"
1157   [(set_attr "type" "extend,load1")]
1160 ;; -------------------------------------------------------------------
1161 ;; Simple arithmetic
1162 ;; -------------------------------------------------------------------
1164 (define_expand "add<mode>3"
1165   [(set
1166     (match_operand:GPI 0 "register_operand" "")
1167     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1168               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1169   ""
1170   "
1171   if (! aarch64_plus_operand (operands[2], VOIDmode))
1172     {
1173       rtx subtarget = ((optimize && can_create_pseudo_p ())
1174                        ? gen_reg_rtx (<MODE>mode) : operands[0]);
1175       HOST_WIDE_INT imm = INTVAL (operands[2]);
1177       if (imm < 0)
1178         imm = -(-imm & ~0xfff);
1179       else
1180         imm &= ~0xfff;
1182       emit_insn (gen_add<mode>3 (subtarget, operands[1], GEN_INT (imm)));
1183       operands[1] = subtarget;
1184       operands[2] = GEN_INT (INTVAL (operands[2]) - imm);
1185     }
1186   "
1189 (define_insn "*addsi3_aarch64"
1190   [(set
1191     (match_operand:SI 0 "register_operand" "=rk,rk,w,rk")
1192     (plus:SI
1193      (match_operand:SI 1 "register_operand" "%rk,rk,w,rk")
1194      (match_operand:SI 2 "aarch64_plus_operand" "I,r,w,J")))]
1195   ""
1196   "@
1197   add\\t%w0, %w1, %2
1198   add\\t%w0, %w1, %w2
1199   add\\t%0.2s, %1.2s, %2.2s
1200   sub\\t%w0, %w1, #%n2"
1201   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm")
1202    (set_attr "simd" "*,*,yes,*")]
1205 ;; zero_extend version of above
1206 (define_insn "*addsi3_aarch64_uxtw"
1207   [(set
1208     (match_operand:DI 0 "register_operand" "=rk,rk,rk")
1209     (zero_extend:DI
1210      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk")
1211               (match_operand:SI 2 "aarch64_plus_operand" "I,r,J"))))]
1212   ""
1213   "@
1214   add\\t%w0, %w1, %2
1215   add\\t%w0, %w1, %w2
1216   sub\\t%w0, %w1, #%n2"
1217   [(set_attr "type" "alu_imm,alu_sreg,alu_imm")]
1220 (define_insn "*adddi3_aarch64"
1221   [(set
1222     (match_operand:DI 0 "register_operand" "=rk,rk,rk,!w")
1223     (plus:DI
1224      (match_operand:DI 1 "register_operand" "%rk,rk,rk,!w")
1225      (match_operand:DI 2 "aarch64_plus_operand" "I,r,J,!w")))]
1226   ""
1227   "@
1228   add\\t%x0, %x1, %2
1229   add\\t%x0, %x1, %x2
1230   sub\\t%x0, %x1, #%n2
1231   add\\t%d0, %d1, %d2"
1232   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,alu_sreg")
1233    (set_attr "simd" "*,*,*,yes")]
1236 (define_expand "addti3"
1237   [(set (match_operand:TI 0 "register_operand" "")
1238         (plus:TI (match_operand:TI 1 "register_operand" "")
1239                  (match_operand:TI 2 "register_operand" "")))]
1240   ""
1242   rtx low = gen_reg_rtx (DImode);
1243   emit_insn (gen_adddi3_compare0 (low, gen_lowpart (DImode, operands[1]),
1244                                   gen_lowpart (DImode, operands[2])));
1246   rtx high = gen_reg_rtx (DImode);
1247   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1248                                  gen_highpart (DImode, operands[2])));
1250   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1251   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1252   DONE;
1255 (define_insn "add<mode>3_compare0"
1256   [(set (reg:CC_NZ CC_REGNUM)
1257         (compare:CC_NZ
1258          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1259                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1260          (const_int 0)))
1261    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1262         (plus:GPI (match_dup 1) (match_dup 2)))]
1263   ""
1264   "@
1265   adds\\t%<w>0, %<w>1, %<w>2
1266   adds\\t%<w>0, %<w>1, %<w>2
1267   subs\\t%<w>0, %<w>1, #%n2"
1268   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1271 ;; zero_extend version of above
1272 (define_insn "*addsi3_compare0_uxtw"
1273   [(set (reg:CC_NZ CC_REGNUM)
1274         (compare:CC_NZ
1275          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1276                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1277          (const_int 0)))
1278    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1279         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1280   ""
1281   "@
1282   adds\\t%w0, %w1, %w2
1283   adds\\t%w0, %w1, %w2
1284   subs\\t%w0, %w1, #%n2"
1285   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1288 (define_insn "*adds_mul_imm_<mode>"
1289   [(set (reg:CC_NZ CC_REGNUM)
1290         (compare:CC_NZ
1291          (plus:GPI (mult:GPI
1292                     (match_operand:GPI 1 "register_operand" "r")
1293                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1294                    (match_operand:GPI 3 "register_operand" "r"))
1295          (const_int 0)))
1296    (set (match_operand:GPI 0 "register_operand" "=r")
1297         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1298                   (match_dup 3)))]
1299   ""
1300   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1301   [(set_attr "type" "alus_shift_imm")]
1304 (define_insn "*subs_mul_imm_<mode>"
1305   [(set (reg:CC_NZ CC_REGNUM)
1306         (compare:CC_NZ
1307          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1308                     (mult:GPI
1309                      (match_operand:GPI 2 "register_operand" "r")
1310                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1311          (const_int 0)))
1312    (set (match_operand:GPI 0 "register_operand" "=r")
1313         (minus:GPI (match_dup 1)
1314                    (mult:GPI (match_dup 2) (match_dup 3))))]
1315   ""
1316   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1317   [(set_attr "type" "alus_shift_imm")]
1320 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1321   [(set (reg:CC_NZ CC_REGNUM)
1322         (compare:CC_NZ
1323          (plus:GPI
1324           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1325           (match_operand:GPI 2 "register_operand" "r"))
1326         (const_int 0)))
1327    (set (match_operand:GPI 0 "register_operand" "=r")
1328         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1329   ""
1330   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1331   [(set_attr "type" "alus_ext")]
1334 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1335   [(set (reg:CC_NZ CC_REGNUM)
1336         (compare:CC_NZ
1337          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1338                     (ANY_EXTEND:GPI
1339                      (match_operand:ALLX 2 "register_operand" "r")))
1340         (const_int 0)))
1341    (set (match_operand:GPI 0 "register_operand" "=r")
1342         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1343   ""
1344   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1345   [(set_attr "type" "alus_ext")]
1348 (define_insn "*adds_<optab><mode>_multp2"
1349   [(set (reg:CC_NZ CC_REGNUM)
1350         (compare:CC_NZ
1351          (plus:GPI (ANY_EXTRACT:GPI
1352                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1353                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1354                     (match_operand 3 "const_int_operand" "n")
1355                     (const_int 0))
1356                    (match_operand:GPI 4 "register_operand" "r"))
1357         (const_int 0)))
1358    (set (match_operand:GPI 0 "register_operand" "=r")
1359         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1360                                    (match_dup 3)
1361                                    (const_int 0))
1362                   (match_dup 4)))]
1363   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1364   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1365   [(set_attr "type" "alus_ext")]
1368 (define_insn "*subs_<optab><mode>_multp2"
1369   [(set (reg:CC_NZ CC_REGNUM)
1370         (compare:CC_NZ
1371          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1372                     (ANY_EXTRACT:GPI
1373                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1374                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1375                      (match_operand 3 "const_int_operand" "n")
1376                      (const_int 0)))
1377         (const_int 0)))
1378    (set (match_operand:GPI 0 "register_operand" "=r")
1379         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1380                                   (mult:GPI (match_dup 1) (match_dup 2))
1381                                   (match_dup 3)
1382                                   (const_int 0))))]
1383   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1384   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1385   [(set_attr "type" "alus_ext")]
1388 (define_insn "*add<mode>3nr_compare0"
1389   [(set (reg:CC_NZ CC_REGNUM)
1390         (compare:CC_NZ
1391          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1392                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
1393          (const_int 0)))]
1394   ""
1395   "@
1396   cmn\\t%<w>0, %<w>1
1397   cmn\\t%<w>0, %<w>1
1398   cmp\\t%<w>0, #%n1"
1399   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1402 (define_insn "*compare_neg<mode>"
1403   [(set (reg:CC_Z CC_REGNUM)
1404         (compare:CC_Z
1405          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
1406          (match_operand:GPI 1 "register_operand" "r")))]
1407   ""
1408   "cmn\\t%<w>1, %<w>0"
1409   [(set_attr "type" "alus_sreg")]
1412 (define_insn "*add_<shift>_<mode>"
1413   [(set (match_operand:GPI 0 "register_operand" "=r")
1414         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
1415                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1416                   (match_operand:GPI 3 "register_operand" "r")))]
1417   ""
1418   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1419   [(set_attr "type" "alu_shift_imm")]
1422 ;; zero_extend version of above
1423 (define_insn "*add_<shift>_si_uxtw"
1424   [(set (match_operand:DI 0 "register_operand" "=r")
1425         (zero_extend:DI
1426          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
1427                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
1428                   (match_operand:SI 3 "register_operand" "r"))))]
1429   ""
1430   "add\\t%w0, %w3, %w1, <shift> %2"
1431   [(set_attr "type" "alu_shift_imm")]
1434 (define_insn "*add_mul_imm_<mode>"
1435   [(set (match_operand:GPI 0 "register_operand" "=r")
1436         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1437                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1438                   (match_operand:GPI 3 "register_operand" "r")))]
1439   ""
1440   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1441   [(set_attr "type" "alu_shift_imm")]
1444 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
1445   [(set (match_operand:GPI 0 "register_operand" "=rk")
1446         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1447                   (match_operand:GPI 2 "register_operand" "r")))]
1448   ""
1449   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1450   [(set_attr "type" "alu_ext")]
1453 ;; zero_extend version of above
1454 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
1455   [(set (match_operand:DI 0 "register_operand" "=rk")
1456         (zero_extend:DI
1457          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
1458                   (match_operand:GPI 2 "register_operand" "r"))))]
1459   ""
1460   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
1461   [(set_attr "type" "alu_ext")]
1464 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
1465   [(set (match_operand:GPI 0 "register_operand" "=rk")
1466         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
1467                                (match_operand:ALLX 1 "register_operand" "r"))
1468                               (match_operand 2 "aarch64_imm3" "Ui3"))
1469                   (match_operand:GPI 3 "register_operand" "r")))]
1470   ""
1471   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1472   [(set_attr "type" "alu_ext")]
1475 ;; zero_extend version of above
1476 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
1477   [(set (match_operand:DI 0 "register_operand" "=rk")
1478         (zero_extend:DI
1479          (plus:SI (ashift:SI (ANY_EXTEND:SI
1480                               (match_operand:SHORT 1 "register_operand" "r"))
1481                              (match_operand 2 "aarch64_imm3" "Ui3"))
1482                   (match_operand:SI 3 "register_operand" "r"))))]
1483   ""
1484   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
1485   [(set_attr "type" "alu_ext")]
1488 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
1489   [(set (match_operand:GPI 0 "register_operand" "=rk")
1490         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
1491                              (match_operand:ALLX 1 "register_operand" "r"))
1492                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1493                   (match_operand:GPI 3 "register_operand" "r")))]
1494   ""
1495   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
1496   [(set_attr "type" "alu_ext")]
1499 ;; zero_extend version of above
1500 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
1501   [(set (match_operand:DI 0 "register_operand" "=rk")
1502         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
1503                              (match_operand:SHORT 1 "register_operand" "r"))
1504                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1505                   (match_operand:SI 3 "register_operand" "r"))))]
1506   ""
1507   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
1508   [(set_attr "type" "alu_ext")]
1511 (define_insn "*add_<optab><mode>_multp2"
1512   [(set (match_operand:GPI 0 "register_operand" "=rk")
1513         (plus:GPI (ANY_EXTRACT:GPI
1514                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1515                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1516                    (match_operand 3 "const_int_operand" "n")
1517                    (const_int 0))
1518                   (match_operand:GPI 4 "register_operand" "r")))]
1519   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1520   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1521   [(set_attr "type" "alu_ext")]
1524 ;; zero_extend version of above
1525 (define_insn "*add_<optab>si_multp2_uxtw"
1526   [(set (match_operand:DI 0 "register_operand" "=rk")
1527         (zero_extend:DI
1528          (plus:SI (ANY_EXTRACT:SI
1529                    (mult:SI (match_operand:SI 1 "register_operand" "r")
1530                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1531                    (match_operand 3 "const_int_operand" "n")
1532                    (const_int 0))
1533                   (match_operand:SI 4 "register_operand" "r"))))]
1534   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
1535   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
1536   [(set_attr "type" "alu_ext")]
1539 (define_insn "add<mode>3_carryin"
1540   [(set
1541     (match_operand:GPI 0 "register_operand" "=r")
1542     (plus:GPI (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1543               (plus:GPI
1544                 (match_operand:GPI 1 "register_operand" "r")
1545                 (match_operand:GPI 2 "register_operand" "r"))))]
1546    ""
1547    "adc\\t%<w>0, %<w>1, %<w>2"
1548   [(set_attr "type" "adc_reg")]
1551 ;; zero_extend version of above
1552 (define_insn "*addsi3_carryin_uxtw"
1553   [(set
1554     (match_operand:DI 0 "register_operand" "=r")
1555     (zero_extend:DI
1556      (plus:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
1557               (plus:SI
1558                (match_operand:SI 1 "register_operand" "r")
1559                (match_operand:SI 2 "register_operand" "r")))))]
1560    ""
1561    "adc\\t%w0, %w1, %w2"
1562   [(set_attr "type" "adc_reg")]
1565 (define_insn "*add<mode>3_carryin_alt1"
1566   [(set
1567     (match_operand:GPI 0 "register_operand" "=r")
1568     (plus:GPI (plus:GPI
1569                 (match_operand:GPI 1 "register_operand" "r")
1570                 (match_operand:GPI 2 "register_operand" "r"))
1571               (geu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
1572    ""
1573    "adc\\t%<w>0, %<w>1, %<w>2"
1574   [(set_attr "type" "adc_reg")]
1577 ;; zero_extend version of above
1578 (define_insn "*addsi3_carryin_alt1_uxtw"
1579   [(set
1580     (match_operand:DI 0 "register_operand" "=r")
1581     (zero_extend:DI
1582      (plus:SI (plus:SI
1583                (match_operand:SI 1 "register_operand" "r")
1584                (match_operand:SI 2 "register_operand" "r"))
1585               (geu:SI (reg:CC CC_REGNUM) (const_int 0)))))]
1586    ""
1587    "adc\\t%w0, %w1, %w2"
1588   [(set_attr "type" "adc_reg")]
1591 (define_insn "*add<mode>3_carryin_alt2"
1592   [(set
1593     (match_operand:GPI 0 "register_operand" "=r")
1594     (plus:GPI (plus:GPI
1595                 (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1596                 (match_operand:GPI 1 "register_operand" "r"))
1597               (match_operand:GPI 2 "register_operand" "r")))]
1598    ""
1599    "adc\\t%<w>0, %<w>1, %<w>2"
1600   [(set_attr "type" "adc_reg")]
1603 ;; zero_extend version of above
1604 (define_insn "*addsi3_carryin_alt2_uxtw"
1605   [(set
1606     (match_operand:DI 0 "register_operand" "=r")
1607     (zero_extend:DI
1608      (plus:SI (plus:SI
1609                (geu:SI (reg:CC CC_REGNUM) (const_int 0))
1610                (match_operand:SI 1 "register_operand" "r"))
1611               (match_operand:SI 2 "register_operand" "r"))))]
1612    ""
1613    "adc\\t%w0, %w1, %w2"
1614   [(set_attr "type" "adc_reg")]
1617 (define_insn "*add<mode>3_carryin_alt3"
1618   [(set
1619     (match_operand:GPI 0 "register_operand" "=r")
1620     (plus:GPI (plus:GPI
1621                 (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1622                 (match_operand:GPI 2 "register_operand" "r"))
1623               (match_operand:GPI 1 "register_operand" "r")))]
1624    ""
1625    "adc\\t%<w>0, %<w>1, %<w>2"
1626   [(set_attr "type" "adc_reg")]
1629 ;; zero_extend version of above
1630 (define_insn "*addsi3_carryin_alt3_uxtw"
1631   [(set
1632     (match_operand:DI 0 "register_operand" "=r")
1633     (zero_extend:DI
1634      (plus:SI (plus:SI
1635                (geu:SI (reg:CC CC_REGNUM) (const_int 0))
1636                (match_operand:SI 2 "register_operand" "r"))
1637               (match_operand:SI 1 "register_operand" "r"))))]
1638    ""
1639    "adc\\t%w0, %w1, %w2"
1640   [(set_attr "type" "adc_reg")]
1643 (define_insn "*add_uxt<mode>_multp2"
1644   [(set (match_operand:GPI 0 "register_operand" "=rk")
1645         (plus:GPI (and:GPI
1646                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1647                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1648                    (match_operand 3 "const_int_operand" "n"))
1649                   (match_operand:GPI 4 "register_operand" "r")))]
1650   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
1651   "*
1652   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1653                                            INTVAL (operands[3])));
1654   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
1655   [(set_attr "type" "alu_ext")]
1658 ;; zero_extend version of above
1659 (define_insn "*add_uxtsi_multp2_uxtw"
1660   [(set (match_operand:DI 0 "register_operand" "=rk")
1661         (zero_extend:DI
1662          (plus:SI (and:SI
1663                    (mult:SI (match_operand:SI 1 "register_operand" "r")
1664                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1665                    (match_operand 3 "const_int_operand" "n"))
1666                   (match_operand:SI 4 "register_operand" "r"))))]
1667   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
1668   "*
1669   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1670                                            INTVAL (operands[3])));
1671   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
1672   [(set_attr "type" "alu_ext")]
1675 (define_insn "subsi3"
1676   [(set (match_operand:SI 0 "register_operand" "=rk")
1677         (minus:SI (match_operand:SI 1 "register_operand" "r")
1678                    (match_operand:SI 2 "register_operand" "r")))]
1679   ""
1680   "sub\\t%w0, %w1, %w2"
1681   [(set_attr "type" "alu_sreg")]
1684 ;; zero_extend version of above
1685 (define_insn "*subsi3_uxtw"
1686   [(set (match_operand:DI 0 "register_operand" "=rk")
1687         (zero_extend:DI
1688          (minus:SI (match_operand:SI 1 "register_operand" "r")
1689                    (match_operand:SI 2 "register_operand" "r"))))]
1690   ""
1691   "sub\\t%w0, %w1, %w2"
1692   [(set_attr "type" "alu_sreg")]
1695 (define_insn "subdi3"
1696   [(set (match_operand:DI 0 "register_operand" "=rk,!w")
1697         (minus:DI (match_operand:DI 1 "register_operand" "r,!w")
1698                    (match_operand:DI 2 "register_operand" "r,!w")))]
1699   ""
1700   "@
1701    sub\\t%x0, %x1, %x2
1702    sub\\t%d0, %d1, %d2"
1703   [(set_attr "type" "alu_sreg, neon_sub")
1704    (set_attr "simd" "*,yes")]
1707 (define_expand "subti3"
1708   [(set (match_operand:TI 0 "register_operand" "")
1709         (minus:TI (match_operand:TI 1 "register_operand" "")
1710                   (match_operand:TI 2 "register_operand" "")))]
1711   ""
1713   rtx low = gen_reg_rtx (DImode);
1714   emit_insn (gen_subdi3_compare0 (low, gen_lowpart (DImode, operands[1]),
1715                                   gen_lowpart (DImode, operands[2])));
1717   rtx high = gen_reg_rtx (DImode);
1718   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
1719                                  gen_highpart (DImode, operands[2])));
1721   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1722   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1723   DONE;
1726 (define_insn "sub<mode>3_compare0"
1727   [(set (reg:CC_NZ CC_REGNUM)
1728         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1729                                   (match_operand:GPI 2 "register_operand" "r"))
1730                        (const_int 0)))
1731    (set (match_operand:GPI 0 "register_operand" "=r")
1732         (minus:GPI (match_dup 1) (match_dup 2)))]
1733   ""
1734   "subs\\t%<w>0, %<w>1, %<w>2"
1735   [(set_attr "type" "alus_sreg")]
1738 ;; zero_extend version of above
1739 (define_insn "*subsi3_compare0_uxtw"
1740   [(set (reg:CC_NZ CC_REGNUM)
1741         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
1742                                  (match_operand:SI 2 "register_operand" "r"))
1743                        (const_int 0)))
1744    (set (match_operand:DI 0 "register_operand" "=r")
1745         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
1746   ""
1747   "subs\\t%w0, %w1, %w2"
1748   [(set_attr "type" "alus_sreg")]
1751 (define_insn "*sub_<shift>_<mode>"
1752   [(set (match_operand:GPI 0 "register_operand" "=r")
1753         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
1754                    (ASHIFT:GPI
1755                     (match_operand:GPI 1 "register_operand" "r")
1756                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
1757   ""
1758   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1759   [(set_attr "type" "alu_shift_imm")]
1762 ;; zero_extend version of above
1763 (define_insn "*sub_<shift>_si_uxtw"
1764   [(set (match_operand:DI 0 "register_operand" "=r")
1765         (zero_extend:DI
1766          (minus:SI (match_operand:SI 3 "register_operand" "r")
1767                    (ASHIFT:SI
1768                     (match_operand:SI 1 "register_operand" "r")
1769                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
1770   ""
1771   "sub\\t%w0, %w3, %w1, <shift> %2"
1772   [(set_attr "type" "alu_shift_imm")]
1775 (define_insn "*sub_mul_imm_<mode>"
1776   [(set (match_operand:GPI 0 "register_operand" "=r")
1777         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
1778                    (mult:GPI
1779                     (match_operand:GPI 1 "register_operand" "r")
1780                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
1781   ""
1782   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1783   [(set_attr "type" "alu_shift_imm")]
1786 ;; zero_extend version of above
1787 (define_insn "*sub_mul_imm_si_uxtw"
1788   [(set (match_operand:DI 0 "register_operand" "=r")
1789         (zero_extend:DI
1790          (minus:SI (match_operand:SI 3 "register_operand" "r")
1791                    (mult:SI
1792                     (match_operand:SI 1 "register_operand" "r")
1793                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
1794   ""
1795   "sub\\t%w0, %w3, %w1, lsl %p2"
1796   [(set_attr "type" "alu_shift_imm")]
1799 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
1800   [(set (match_operand:GPI 0 "register_operand" "=rk")
1801         (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1802                    (ANY_EXTEND:GPI
1803                     (match_operand:ALLX 2 "register_operand" "r"))))]
1804   ""
1805   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1806   [(set_attr "type" "alu_ext")]
1809 ;; zero_extend version of above
1810 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
1811   [(set (match_operand:DI 0 "register_operand" "=rk")
1812         (zero_extend:DI
1813          (minus:SI (match_operand:SI 1 "register_operand" "r")
1814                    (ANY_EXTEND:SI
1815                     (match_operand:SHORT 2 "register_operand" "r")))))]
1816   ""
1817   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
1818   [(set_attr "type" "alu_ext")]
1821 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
1822   [(set (match_operand:GPI 0 "register_operand" "=rk")
1823         (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1824                    (ashift:GPI (ANY_EXTEND:GPI
1825                                 (match_operand:ALLX 2 "register_operand" "r"))
1826                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
1827   ""
1828   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1829   [(set_attr "type" "alu_ext")]
1832 ;; zero_extend version of above
1833 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
1834   [(set (match_operand:DI 0 "register_operand" "=rk")
1835         (zero_extend:DI
1836          (minus:SI (match_operand:SI 1 "register_operand" "r")
1837                    (ashift:SI (ANY_EXTEND:SI
1838                                (match_operand:SHORT 2 "register_operand" "r"))
1839                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
1840   ""
1841   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
1842   [(set_attr "type" "alu_ext")]
1845 (define_insn "*sub_<optab><mode>_multp2"
1846   [(set (match_operand:GPI 0 "register_operand" "=rk")
1847         (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1848                    (ANY_EXTRACT:GPI
1849                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1850                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1851                     (match_operand 3 "const_int_operand" "n")
1852                     (const_int 0))))]
1853   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1854   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1855   [(set_attr "type" "alu_ext")]
1858 ;; zero_extend version of above
1859 (define_insn "*sub_<optab>si_multp2_uxtw"
1860   [(set (match_operand:DI 0 "register_operand" "=rk")
1861         (zero_extend:DI
1862          (minus:SI (match_operand:SI 4 "register_operand" "r")
1863                    (ANY_EXTRACT:SI
1864                     (mult:SI (match_operand:SI 1 "register_operand" "r")
1865                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1866                     (match_operand 3 "const_int_operand" "n")
1867                     (const_int 0)))))]
1868   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
1869   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
1870   [(set_attr "type" "alu_ext")]
1873 (define_insn "sub<mode>3_carryin"
1874   [(set
1875     (match_operand:GPI 0 "register_operand" "=r")
1876     (minus:GPI (minus:GPI
1877                 (match_operand:GPI 1 "register_operand" "r")
1878                 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0)))
1879                (match_operand:GPI 2 "register_operand" "r")))]
1880    ""
1881    "sbc\\t%<w>0, %<w>1, %<w>2"
1882   [(set_attr "type" "adc_reg")]
1885 ;; zero_extend version of the above
1886 (define_insn "*subsi3_carryin_uxtw"
1887   [(set
1888     (match_operand:DI 0 "register_operand" "=r")
1889     (zero_extend:DI
1890      (minus:SI (minus:SI
1891                 (match_operand:SI 1 "register_operand" "r")
1892                 (ltu:SI (reg:CC CC_REGNUM) (const_int 0)))
1893                (match_operand:SI 2 "register_operand" "r"))))]
1894    ""
1895    "sbc\\t%w0, %w1, %w2"
1896   [(set_attr "type" "adc_reg")]
1899 (define_insn "*sub_uxt<mode>_multp2"
1900   [(set (match_operand:GPI 0 "register_operand" "=rk")
1901         (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1902                    (and:GPI
1903                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1904                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1905                     (match_operand 3 "const_int_operand" "n"))))]
1906   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
1907   "*
1908   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1909                                            INTVAL (operands[3])));
1910   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
1911   [(set_attr "type" "alu_ext")]
1914 ;; zero_extend version of above
1915 (define_insn "*sub_uxtsi_multp2_uxtw"
1916   [(set (match_operand:DI 0 "register_operand" "=rk")
1917         (zero_extend:DI
1918          (minus:SI (match_operand:SI 4 "register_operand" "r")
1919                    (and:SI
1920                     (mult:SI (match_operand:SI 1 "register_operand" "r")
1921                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1922                     (match_operand 3 "const_int_operand" "n")))))]
1923   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
1924   "*
1925   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1926                                            INTVAL (operands[3])));
1927   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
1928   [(set_attr "type" "alu_ext")]
1931 (define_insn_and_split "absdi2"
1932   [(set (match_operand:DI 0 "register_operand" "=r,w")
1933         (abs:DI (match_operand:DI 1 "register_operand" "r,w")))
1934    (clobber (match_scratch:DI 2 "=&r,X"))]
1935   ""
1936   "@
1937    #
1938    abs\\t%d0, %d1"
1939   "reload_completed
1940    && GP_REGNUM_P (REGNO (operands[0]))
1941    && GP_REGNUM_P (REGNO (operands[1]))"
1942   [(const_int 0)]
1943   {
1944     emit_insn (gen_rtx_SET (VOIDmode, operands[2],
1945                             gen_rtx_XOR (DImode,
1946                                          gen_rtx_ASHIFTRT (DImode,
1947                                                            operands[1],
1948                                                            GEN_INT (63)),
1949                                          operands[1])));
1950     emit_insn (gen_rtx_SET (VOIDmode,
1951                             operands[0],
1952                             gen_rtx_MINUS (DImode,
1953                                            operands[2],
1954                                            gen_rtx_ASHIFTRT (DImode,
1955                                                              operands[1],
1956                                                              GEN_INT (63)))));
1957     DONE;
1958   }
1959   [(set_attr "type" "alu_sreg")]
1962 (define_insn "neg<mode>2"
1963   [(set (match_operand:GPI 0 "register_operand" "=r,w")
1964         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
1965   ""
1966   "@
1967    neg\\t%<w>0, %<w>1
1968    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
1969   [(set_attr "type" "alu_sreg, neon_neg<q>")
1970    (set_attr "simd" "*,yes")]
1973 ;; zero_extend version of above
1974 (define_insn "*negsi2_uxtw"
1975   [(set (match_operand:DI 0 "register_operand" "=r")
1976         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
1977   ""
1978   "neg\\t%w0, %w1"
1979   [(set_attr "type" "alu_sreg")]
1982 (define_insn "*ngc<mode>"
1983   [(set (match_operand:GPI 0 "register_operand" "=r")
1984         (minus:GPI (neg:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0)))
1985                    (match_operand:GPI 1 "register_operand" "r")))]
1986   ""
1987   "ngc\\t%<w>0, %<w>1"
1988   [(set_attr "type" "adc_reg")]
1991 (define_insn "*ngcsi_uxtw"
1992   [(set (match_operand:DI 0 "register_operand" "=r")
1993         (zero_extend:DI
1994          (minus:SI (neg:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0)))
1995                    (match_operand:SI 1 "register_operand" "r"))))]
1996   ""
1997   "ngc\\t%w0, %w1"
1998   [(set_attr "type" "adc_reg")]
2001 (define_insn "*neg<mode>2_compare0"
2002   [(set (reg:CC_NZ CC_REGNUM)
2003         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2004                        (const_int 0)))
2005    (set (match_operand:GPI 0 "register_operand" "=r")
2006         (neg:GPI (match_dup 1)))]
2007   ""
2008   "negs\\t%<w>0, %<w>1"
2009   [(set_attr "type" "alus_sreg")]
2012 ;; zero_extend version of above
2013 (define_insn "*negsi2_compare0_uxtw"
2014   [(set (reg:CC_NZ CC_REGNUM)
2015         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2016                        (const_int 0)))
2017    (set (match_operand:DI 0 "register_operand" "=r")
2018         (zero_extend:DI (neg:SI (match_dup 1))))]
2019   ""
2020   "negs\\t%w0, %w1"
2021   [(set_attr "type" "alus_sreg")]
2024 (define_insn "*neg_<shift><mode>3_compare0"
2025   [(set (reg:CC_NZ CC_REGNUM)
2026         (compare:CC_NZ
2027          (neg:GPI (ASHIFT:GPI
2028                    (match_operand:GPI 1 "register_operand" "r")
2029                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2030          (const_int 0)))
2031    (set (match_operand:GPI 0 "register_operand" "=r")
2032         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2033   ""
2034   "negs\\t%<w>0, %<w>1, <shift> %2"
2035   [(set_attr "type" "alus_shift_imm")]
2038 (define_insn "*neg_<shift>_<mode>2"
2039   [(set (match_operand:GPI 0 "register_operand" "=r")
2040         (neg:GPI (ASHIFT:GPI
2041                   (match_operand:GPI 1 "register_operand" "r")
2042                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2043   ""
2044   "neg\\t%<w>0, %<w>1, <shift> %2"
2045   [(set_attr "type" "alu_shift_imm")]
2048 ;; zero_extend version of above
2049 (define_insn "*neg_<shift>_si2_uxtw"
2050   [(set (match_operand:DI 0 "register_operand" "=r")
2051         (zero_extend:DI
2052          (neg:SI (ASHIFT:SI
2053                   (match_operand:SI 1 "register_operand" "r")
2054                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2055   ""
2056   "neg\\t%w0, %w1, <shift> %2"
2057   [(set_attr "type" "alu_shift_imm")]
2060 (define_insn "*neg_mul_imm_<mode>2"
2061   [(set (match_operand:GPI 0 "register_operand" "=r")
2062         (neg:GPI (mult:GPI
2063                   (match_operand:GPI 1 "register_operand" "r")
2064                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2065   ""
2066   "neg\\t%<w>0, %<w>1, lsl %p2"
2067   [(set_attr "type" "alu_shift_imm")]
2070 ;; zero_extend version of above
2071 (define_insn "*neg_mul_imm_si2_uxtw"
2072   [(set (match_operand:DI 0 "register_operand" "=r")
2073         (zero_extend:DI
2074          (neg:SI (mult:SI
2075                   (match_operand:SI 1 "register_operand" "r")
2076                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2077   ""
2078   "neg\\t%w0, %w1, lsl %p2"
2079   [(set_attr "type" "alu_shift_imm")]
2082 (define_insn "mul<mode>3"
2083   [(set (match_operand:GPI 0 "register_operand" "=r")
2084         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2085                   (match_operand:GPI 2 "register_operand" "r")))]
2086   ""
2087   "mul\\t%<w>0, %<w>1, %<w>2"
2088   [(set_attr "type" "mul")]
2091 ;; zero_extend version of above
2092 (define_insn "*mulsi3_uxtw"
2093   [(set (match_operand:DI 0 "register_operand" "=r")
2094         (zero_extend:DI
2095          (mult:SI (match_operand:SI 1 "register_operand" "r")
2096                   (match_operand:SI 2 "register_operand" "r"))))]
2097   ""
2098   "mul\\t%w0, %w1, %w2"
2099   [(set_attr "type" "mul")]
2102 (define_insn "madd<mode>"
2103   [(set (match_operand:GPI 0 "register_operand" "=r")
2104         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2105                             (match_operand:GPI 2 "register_operand" "r"))
2106                   (match_operand:GPI 3 "register_operand" "r")))]
2107   ""
2108   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2109   [(set_attr "type" "mla")]
2112 ;; zero_extend version of above
2113 (define_insn "*maddsi_uxtw"
2114   [(set (match_operand:DI 0 "register_operand" "=r")
2115         (zero_extend:DI
2116          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2117                            (match_operand:SI 2 "register_operand" "r"))
2118                   (match_operand:SI 3 "register_operand" "r"))))]
2119   ""
2120   "madd\\t%w0, %w1, %w2, %w3"
2121   [(set_attr "type" "mla")]
2124 (define_insn "*msub<mode>"
2125   [(set (match_operand:GPI 0 "register_operand" "=r")
2126         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2127                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2128                              (match_operand:GPI 2 "register_operand" "r"))))]
2130   ""
2131   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2132   [(set_attr "type" "mla")]
2135 ;; zero_extend version of above
2136 (define_insn "*msubsi_uxtw"
2137   [(set (match_operand:DI 0 "register_operand" "=r")
2138         (zero_extend:DI
2139          (minus:SI (match_operand:SI 3 "register_operand" "r")
2140                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2141                             (match_operand:SI 2 "register_operand" "r")))))]
2143   ""
2144   "msub\\t%w0, %w1, %w2, %w3"
2145   [(set_attr "type" "mla")]
2148 (define_insn "*mul<mode>_neg"
2149   [(set (match_operand:GPI 0 "register_operand" "=r")
2150         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2151                   (match_operand:GPI 2 "register_operand" "r")))]
2153   ""
2154   "mneg\\t%<w>0, %<w>1, %<w>2"
2155   [(set_attr "type" "mul")]
2158 ;; zero_extend version of above
2159 (define_insn "*mulsi_neg_uxtw"
2160   [(set (match_operand:DI 0 "register_operand" "=r")
2161         (zero_extend:DI
2162          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2163                   (match_operand:SI 2 "register_operand" "r"))))]
2165   ""
2166   "mneg\\t%w0, %w1, %w2"
2167   [(set_attr "type" "mul")]
2170 (define_insn "<su_optab>mulsidi3"
2171   [(set (match_operand:DI 0 "register_operand" "=r")
2172         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2173                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2174   ""
2175   "<su>mull\\t%0, %w1, %w2"
2176   [(set_attr "type" "<su>mull")]
2179 (define_insn "<su_optab>maddsidi4"
2180   [(set (match_operand:DI 0 "register_operand" "=r")
2181         (plus:DI (mult:DI
2182                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2183                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2184                  (match_operand:DI 3 "register_operand" "r")))]
2185   ""
2186   "<su>maddl\\t%0, %w1, %w2, %3"
2187   [(set_attr "type" "<su>mlal")]
2190 (define_insn "<su_optab>msubsidi4"
2191   [(set (match_operand:DI 0 "register_operand" "=r")
2192         (minus:DI
2193          (match_operand:DI 3 "register_operand" "r")
2194          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2195                   (ANY_EXTEND:DI
2196                    (match_operand:SI 2 "register_operand" "r")))))]
2197   ""
2198   "<su>msubl\\t%0, %w1, %w2, %3"
2199   [(set_attr "type" "<su>mlal")]
2202 (define_insn "*<su_optab>mulsidi_neg"
2203   [(set (match_operand:DI 0 "register_operand" "=r")
2204         (mult:DI (neg:DI
2205                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2206                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2207   ""
2208   "<su>mnegl\\t%0, %w1, %w2"
2209   [(set_attr "type" "<su>mull")]
2212 (define_expand "<su_optab>mulditi3"
2213   [(set (match_operand:TI 0 "register_operand")
2214         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2215                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2216   ""
2218   rtx low = gen_reg_rtx (DImode);
2219   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2221   rtx high = gen_reg_rtx (DImode);
2222   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2224   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2225   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2226   DONE;
2229 ;; The default expansion of multi3 using umuldi3_highpart will perform
2230 ;; the additions in an order that fails to combine into two madd insns.
2231 (define_expand "multi3"
2232   [(set (match_operand:TI 0 "register_operand")
2233         (mult:TI (match_operand:TI 1 "register_operand")
2234                  (match_operand:TI 2 "register_operand")))]
2235   ""
2237   rtx l0 = gen_reg_rtx (DImode);
2238   rtx l1 = gen_lowpart (DImode, operands[1]);
2239   rtx l2 = gen_lowpart (DImode, operands[2]);
2240   rtx h0 = gen_reg_rtx (DImode);
2241   rtx h1 = gen_highpart (DImode, operands[1]);
2242   rtx h2 = gen_highpart (DImode, operands[2]);
2244   emit_insn (gen_muldi3 (l0, l1, l2));
2245   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2246   emit_insn (gen_madddi (h0, h1, l2, h0));
2247   emit_insn (gen_madddi (h0, l1, h2, h0));
2249   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2250   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2251   DONE;
2254 (define_insn "<su>muldi3_highpart"
2255   [(set (match_operand:DI 0 "register_operand" "=r")
2256         (truncate:DI
2257          (lshiftrt:TI
2258           (mult:TI
2259            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2260            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2261           (const_int 64))))]
2262   ""
2263   "<su>mulh\\t%0, %1, %2"
2264   [(set_attr "type" "<su>mull")]
2267 (define_insn "<su_optab>div<mode>3"
2268   [(set (match_operand:GPI 0 "register_operand" "=r")
2269         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2270                      (match_operand:GPI 2 "register_operand" "r")))]
2271   ""
2272   "<su>div\\t%<w>0, %<w>1, %<w>2"
2273   [(set_attr "type" "<su>div")]
2276 ;; zero_extend version of above
2277 (define_insn "*<su_optab>divsi3_uxtw"
2278   [(set (match_operand:DI 0 "register_operand" "=r")
2279         (zero_extend:DI
2280          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2281                      (match_operand:SI 2 "register_operand" "r"))))]
2282   ""
2283   "<su>div\\t%w0, %w1, %w2"
2284   [(set_attr "type" "<su>div")]
2287 ;; -------------------------------------------------------------------
2288 ;; Comparison insns
2289 ;; -------------------------------------------------------------------
2291 (define_insn "*cmp<mode>"
2292   [(set (reg:CC CC_REGNUM)
2293         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2294                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2295   ""
2296   "@
2297    cmp\\t%<w>0, %<w>1
2298    cmp\\t%<w>0, %<w>1
2299    cmn\\t%<w>0, #%n1"
2300   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2303 (define_insn "*cmp<mode>"
2304   [(set (reg:CCFP CC_REGNUM)
2305         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2306                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2307    "TARGET_FLOAT"
2308    "@
2309     fcmp\\t%<s>0, #0.0
2310     fcmp\\t%<s>0, %<s>1"
2311   [(set_attr "type" "fcmp<s>")]
2314 (define_insn "*cmpe<mode>"
2315   [(set (reg:CCFPE CC_REGNUM)
2316         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2317                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2318    "TARGET_FLOAT"
2319    "@
2320     fcmpe\\t%<s>0, #0.0
2321     fcmpe\\t%<s>0, %<s>1"
2322   [(set_attr "type" "fcmp<s>")]
2325 (define_insn "*cmp_swp_<shift>_reg<mode>"
2326   [(set (reg:CC_SWP CC_REGNUM)
2327         (compare:CC_SWP (ASHIFT:GPI
2328                          (match_operand:GPI 0 "register_operand" "r")
2329                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2330                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2331   ""
2332   "cmp\\t%<w>2, %<w>0, <shift> %1"
2333   [(set_attr "type" "alus_shift_imm")]
2336 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
2337   [(set (reg:CC_SWP CC_REGNUM)
2338         (compare:CC_SWP (ANY_EXTEND:GPI
2339                          (match_operand:ALLX 0 "register_operand" "r"))
2340                         (match_operand:GPI 1 "register_operand" "r")))]
2341   ""
2342   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
2343   [(set_attr "type" "alus_ext")]
2346 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
2347   [(set (reg:CC_SWP CC_REGNUM)
2348         (compare:CC_SWP (ashift:GPI
2349                          (ANY_EXTEND:GPI
2350                           (match_operand:ALLX 0 "register_operand" "r"))
2351                          (match_operand 1 "aarch64_imm3" "Ui3"))
2352         (match_operand:GPI 2 "register_operand" "r")))]
2353   ""
2354   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
2355   [(set_attr "type" "alus_ext")]
2358 ;; -------------------------------------------------------------------
2359 ;; Store-flag and conditional select insns
2360 ;; -------------------------------------------------------------------
2362 (define_expand "cstore<mode>4"
2363   [(set (match_operand:SI 0 "register_operand" "")
2364         (match_operator:SI 1 "aarch64_comparison_operator"
2365          [(match_operand:GPI 2 "register_operand" "")
2366           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
2367   ""
2368   "
2369   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2370                                       operands[3]);
2371   operands[3] = const0_rtx;
2372   "
2375 (define_expand "cstore<mode>4"
2376   [(set (match_operand:SI 0 "register_operand" "")
2377         (match_operator:SI 1 "aarch64_comparison_operator"
2378          [(match_operand:GPF 2 "register_operand" "")
2379           (match_operand:GPF 3 "register_operand" "")]))]
2380   ""
2381   "
2382   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2383                                       operands[3]);
2384   operands[3] = const0_rtx;
2385   "
2388 (define_insn "*cstore<mode>_insn"
2389   [(set (match_operand:ALLI 0 "register_operand" "=r")
2390         (match_operator:ALLI 1 "aarch64_comparison_operator"
2391          [(match_operand 2 "cc_register" "") (const_int 0)]))]
2392   ""
2393   "cset\\t%<w>0, %m1"
2394   [(set_attr "type" "csel")]
2397 ;; zero_extend version of the above
2398 (define_insn "*cstoresi_insn_uxtw"
2399   [(set (match_operand:DI 0 "register_operand" "=r")
2400         (zero_extend:DI
2401          (match_operator:SI 1 "aarch64_comparison_operator"
2402           [(match_operand 2 "cc_register" "") (const_int 0)])))]
2403   ""
2404   "cset\\t%w0, %m1"
2405   [(set_attr "type" "csel")]
2408 (define_insn "cstore<mode>_neg"
2409   [(set (match_operand:ALLI 0 "register_operand" "=r")
2410         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator"
2411                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
2412   ""
2413   "csetm\\t%<w>0, %m1"
2414   [(set_attr "type" "csel")]
2417 ;; zero_extend version of the above
2418 (define_insn "*cstoresi_neg_uxtw"
2419   [(set (match_operand:DI 0 "register_operand" "=r")
2420         (zero_extend:DI
2421          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator"
2422                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
2423   ""
2424   "csetm\\t%w0, %m1"
2425   [(set_attr "type" "csel")]
2428 (define_expand "cmov<mode>6"
2429   [(set (match_operand:GPI 0 "register_operand" "")
2430         (if_then_else:GPI
2431          (match_operator 1 "aarch64_comparison_operator"
2432           [(match_operand:GPI 2 "register_operand" "")
2433            (match_operand:GPI 3 "aarch64_plus_operand" "")])
2434          (match_operand:GPI 4 "register_operand" "")
2435          (match_operand:GPI 5 "register_operand" "")))]
2436   ""
2437   "
2438   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2439                                       operands[3]);
2440   operands[3] = const0_rtx;
2441   "
2444 (define_expand "cmov<mode>6"
2445   [(set (match_operand:GPF 0 "register_operand" "")
2446         (if_then_else:GPF
2447          (match_operator 1 "aarch64_comparison_operator"
2448           [(match_operand:GPF 2 "register_operand" "")
2449            (match_operand:GPF 3 "register_operand" "")])
2450          (match_operand:GPF 4 "register_operand" "")
2451          (match_operand:GPF 5 "register_operand" "")))]
2452   ""
2453   "
2454   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2455                                       operands[3]);
2456   operands[3] = const0_rtx;
2457   "
2460 (define_insn "*cmov<mode>_insn"
2461   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
2462         (if_then_else:ALLI
2463          (match_operator 1 "aarch64_comparison_operator"
2464           [(match_operand 2 "cc_register" "") (const_int 0)])
2465          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
2466          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
2467   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
2468      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
2469   ;; Final two alternatives should be unreachable, but included for completeness
2470   "@
2471    csel\\t%<w>0, %<w>3, %<w>4, %m1
2472    csinv\\t%<w>0, %<w>3, <w>zr, %m1
2473    csinv\\t%<w>0, %<w>4, <w>zr, %M1
2474    csinc\\t%<w>0, %<w>3, <w>zr, %m1
2475    csinc\\t%<w>0, %<w>4, <w>zr, %M1
2476    mov\\t%<w>0, -1
2477    mov\\t%<w>0, 1"
2478   [(set_attr "type" "csel")]
2481 ;; zero_extend version of above
2482 (define_insn "*cmovsi_insn_uxtw"
2483   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
2484         (zero_extend:DI
2485          (if_then_else:SI
2486           (match_operator 1 "aarch64_comparison_operator"
2487            [(match_operand 2 "cc_register" "") (const_int 0)])
2488           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
2489           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
2490   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
2491      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
2492   ;; Final two alternatives should be unreachable, but included for completeness
2493   "@
2494    csel\\t%w0, %w3, %w4, %m1
2495    csinv\\t%w0, %w3, wzr, %m1
2496    csinv\\t%w0, %w4, wzr, %M1
2497    csinc\\t%w0, %w3, wzr, %m1
2498    csinc\\t%w0, %w4, wzr, %M1
2499    mov\\t%w0, -1
2500    mov\\t%w0, 1"
2501   [(set_attr "type" "csel")]
2504 (define_insn "*cmov<mode>_insn"
2505   [(set (match_operand:GPF 0 "register_operand" "=w")
2506         (if_then_else:GPF
2507          (match_operator 1 "aarch64_comparison_operator"
2508           [(match_operand 2 "cc_register" "") (const_int 0)])
2509          (match_operand:GPF 3 "register_operand" "w")
2510          (match_operand:GPF 4 "register_operand" "w")))]
2511   "TARGET_FLOAT"
2512   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
2513   [(set_attr "type" "fcsel")]
2516 (define_expand "mov<mode>cc"
2517   [(set (match_operand:ALLI 0 "register_operand" "")
2518         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
2519                            (match_operand:ALLI 2 "register_operand" "")
2520                            (match_operand:ALLI 3 "register_operand" "")))]
2521   ""
2522   {
2523     rtx ccreg;
2524     enum rtx_code code = GET_CODE (operands[1]);
2526     if (code == UNEQ || code == LTGT)
2527       FAIL;
2529     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
2530                                   XEXP (operands[1], 1));
2531     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
2532   }
2535 (define_expand "mov<GPF:mode><GPI:mode>cc"
2536   [(set (match_operand:GPI 0 "register_operand" "")
2537         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
2538                           (match_operand:GPF 2 "register_operand" "")
2539                           (match_operand:GPF 3 "register_operand" "")))]
2540   ""
2541   {
2542     rtx ccreg;
2543     enum rtx_code code = GET_CODE (operands[1]);
2545     if (code == UNEQ || code == LTGT)
2546       FAIL;
2548     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
2549                                   XEXP (operands[1], 1));
2550     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
2551   }
2554 (define_expand "mov<mode>cc"
2555   [(set (match_operand:GPF 0 "register_operand" "")
2556         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
2557                           (match_operand:GPF 2 "register_operand" "")
2558                           (match_operand:GPF 3 "register_operand" "")))]
2559   ""
2560   {
2561     rtx ccreg;
2562     enum rtx_code code = GET_CODE (operands[1]);
2564     if (code == UNEQ || code == LTGT)
2565       FAIL;
2567     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
2568                                   XEXP (operands[1], 1));
2569     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
2570   }
2574 ;; CRC32 instructions.
2575 (define_insn "aarch64_<crc_variant>"
2576   [(set (match_operand:SI 0 "register_operand" "=r")
2577         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2578                     (match_operand:<crc_mode> 2 "register_operand" "r")]
2579          CRC))]
2580   "TARGET_CRC32"
2581   {
2582     if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
2583       return "<crc_variant>\\t%w0, %w1, %x2";
2584     else
2585       return "<crc_variant>\\t%w0, %w1, %w2";
2586   }
2587   [(set_attr "type" "crc")]
2590 (define_insn "*csinc2<mode>_insn"
2591   [(set (match_operand:GPI 0 "register_operand" "=r")
2592         (plus:GPI (match_operator:GPI 2 "aarch64_comparison_operator"
2593                   [(match_operand:CC 3 "cc_register" "") (const_int 0)])
2594                  (match_operand:GPI 1 "register_operand" "r")))]
2595   ""
2596   "csinc\\t%<w>0, %<w>1, %<w>1, %M2"
2597   [(set_attr "type" "csel")]
2600 (define_insn "csinc3<mode>_insn"
2601   [(set (match_operand:GPI 0 "register_operand" "=r")
2602         (if_then_else:GPI
2603           (match_operator:GPI 1 "aarch64_comparison_operator"
2604            [(match_operand:CC 2 "cc_register" "") (const_int 0)])
2605           (plus:GPI (match_operand:GPI 3 "register_operand" "r")
2606                     (const_int 1))
2607           (match_operand:GPI 4 "aarch64_reg_or_zero" "rZ")))]
2608   ""
2609   "csinc\\t%<w>0, %<w>4, %<w>3, %M1"
2610   [(set_attr "type" "csel")]
2613 (define_insn "*csinv3<mode>_insn"
2614   [(set (match_operand:GPI 0 "register_operand" "=r")
2615         (if_then_else:GPI
2616           (match_operator:GPI 1 "aarch64_comparison_operator"
2617            [(match_operand:CC 2 "cc_register" "") (const_int 0)])
2618           (not:GPI (match_operand:GPI 3 "register_operand" "r"))
2619           (match_operand:GPI 4 "aarch64_reg_or_zero" "rZ")))]
2620   ""
2621   "csinv\\t%<w>0, %<w>4, %<w>3, %M1"
2622   [(set_attr "type" "csel")]
2625 (define_insn "*csneg3<mode>_insn"
2626   [(set (match_operand:GPI 0 "register_operand" "=r")
2627         (if_then_else:GPI
2628           (match_operator:GPI 1 "aarch64_comparison_operator"
2629            [(match_operand:CC 2 "cc_register" "") (const_int 0)])
2630           (neg:GPI (match_operand:GPI 3 "register_operand" "r"))
2631           (match_operand:GPI 4 "aarch64_reg_or_zero" "rZ")))]
2632   ""
2633   "csneg\\t%<w>0, %<w>4, %<w>3, %M1"
2634   [(set_attr "type" "csel")]
2637 ;; -------------------------------------------------------------------
2638 ;; Logical operations
2639 ;; -------------------------------------------------------------------
2641 (define_insn "<optab><mode>3"
2642   [(set (match_operand:GPI 0 "register_operand" "=r,rk")
2643         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r")
2644                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>")))]
2645   ""
2646   "<logical>\\t%<w>0, %<w>1, %<w>2"
2647   [(set_attr "type" "logic_reg,logic_imm")]
2650 ;; zero_extend version of above
2651 (define_insn "*<optab>si3_uxtw"
2652   [(set (match_operand:DI 0 "register_operand" "=r,rk")
2653         (zero_extend:DI
2654          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
2655                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
2656   ""
2657   "<logical>\\t%w0, %w1, %w2"
2658   [(set_attr "type" "logic_reg,logic_imm")]
2661 (define_insn "*and<mode>3_compare0"
2662   [(set (reg:CC_NZ CC_REGNUM)
2663         (compare:CC_NZ
2664          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
2665                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
2666          (const_int 0)))
2667    (set (match_operand:GPI 0 "register_operand" "=r,r")
2668         (and:GPI (match_dup 1) (match_dup 2)))]
2669   ""
2670   "ands\\t%<w>0, %<w>1, %<w>2"
2671   [(set_attr "type" "logics_reg,logics_imm")]
2674 ;; zero_extend version of above
2675 (define_insn "*andsi3_compare0_uxtw"
2676   [(set (reg:CC_NZ CC_REGNUM)
2677         (compare:CC_NZ
2678          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
2679                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
2680          (const_int 0)))
2681    (set (match_operand:DI 0 "register_operand" "=r,r")
2682         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
2683   ""
2684   "ands\\t%w0, %w1, %w2"
2685   [(set_attr "type" "logics_reg,logics_imm")]
2688 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
2689   [(set (reg:CC_NZ CC_REGNUM)
2690         (compare:CC_NZ
2691          (and:GPI (SHIFT:GPI
2692                    (match_operand:GPI 1 "register_operand" "r")
2693                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2694                   (match_operand:GPI 3 "register_operand" "r"))
2695          (const_int 0)))
2696    (set (match_operand:GPI 0 "register_operand" "=r")
2697         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
2698   ""
2699   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
2700   [(set_attr "type" "logics_shift_imm")]
2703 ;; zero_extend version of above
2704 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
2705   [(set (reg:CC_NZ CC_REGNUM)
2706         (compare:CC_NZ
2707          (and:SI (SHIFT:SI
2708                   (match_operand:SI 1 "register_operand" "r")
2709                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2710                  (match_operand:SI 3 "register_operand" "r"))
2711          (const_int 0)))
2712    (set (match_operand:DI 0 "register_operand" "=r")
2713         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
2714                                 (match_dup 3))))]
2715   ""
2716   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
2717   [(set_attr "type" "logics_shift_imm")]
2720 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
2721   [(set (match_operand:GPI 0 "register_operand" "=r")
2722         (LOGICAL:GPI (SHIFT:GPI
2723                       (match_operand:GPI 1 "register_operand" "r")
2724                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2725                      (match_operand:GPI 3 "register_operand" "r")))]
2726   ""
2727   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
2728   [(set_attr "type" "logic_shift_imm")]
2731 (define_insn "*<optab>_rol<mode>3"
2732   [(set (match_operand:GPI 0 "register_operand" "=r")
2733         (LOGICAL:GPI (rotate:GPI
2734                       (match_operand:GPI 1 "register_operand" "r")
2735                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2736                      (match_operand:GPI 3 "register_operand" "r")))]
2737   ""
2738   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
2739   [(set_attr "type" "logic_shift_imm")]
2742 ;; zero_extend versions of above
2743 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
2744   [(set (match_operand:DI 0 "register_operand" "=r")
2745         (zero_extend:DI
2746          (LOGICAL:SI (SHIFT:SI
2747                       (match_operand:SI 1 "register_operand" "r")
2748                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2749                      (match_operand:SI 3 "register_operand" "r"))))]
2750   ""
2751   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
2752   [(set_attr "type" "logic_shift_imm")]
2755 (define_insn "*<optab>_rolsi3_uxtw"
2756   [(set (match_operand:DI 0 "register_operand" "=r")
2757         (zero_extend:DI
2758          (LOGICAL:SI (rotate:SI
2759                       (match_operand:SI 1 "register_operand" "r")
2760                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2761                      (match_operand:SI 3 "register_operand" "r"))))]
2762   ""
2763   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
2764   [(set_attr "type" "logic_shift_imm")]
2767 (define_insn "one_cmpl<mode>2"
2768   [(set (match_operand:GPI 0 "register_operand" "=r")
2769         (not:GPI (match_operand:GPI 1 "register_operand" "r")))]
2770   ""
2771   "mvn\\t%<w>0, %<w>1"
2772   [(set_attr "type" "logic_reg")]
2775 (define_insn "*one_cmpl_<optab><mode>2"
2776   [(set (match_operand:GPI 0 "register_operand" "=r")
2777         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2778                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2779   ""
2780   "mvn\\t%<w>0, %<w>1, <shift> %2"
2781   [(set_attr "type" "logic_shift_imm")]
2784 (define_insn "*<LOGICAL:optab>_one_cmpl<mode>3"
2785   [(set (match_operand:GPI 0 "register_operand" "=r")
2786         (LOGICAL:GPI (not:GPI
2787                       (match_operand:GPI 1 "register_operand" "r"))
2788                      (match_operand:GPI 2 "register_operand" "r")))]
2789   ""
2790   "<LOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1"
2791   [(set_attr "type" "logic_reg")]
2794 (define_insn "*and_one_cmpl<mode>3_compare0"
2795   [(set (reg:CC_NZ CC_REGNUM)
2796         (compare:CC_NZ
2797          (and:GPI (not:GPI
2798                    (match_operand:GPI 1 "register_operand" "r"))
2799                   (match_operand:GPI 2 "register_operand" "r"))
2800          (const_int 0)))
2801    (set (match_operand:GPI 0 "register_operand" "=r")
2802         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
2803   ""
2804   "bics\\t%<w>0, %<w>2, %<w>1"
2805   [(set_attr "type" "logics_reg")]
2808 ;; zero_extend version of above
2809 (define_insn "*and_one_cmplsi3_compare0_uxtw"
2810   [(set (reg:CC_NZ CC_REGNUM)
2811         (compare:CC_NZ
2812          (and:SI (not:SI
2813                   (match_operand:SI 1 "register_operand" "r"))
2814                  (match_operand:SI 2 "register_operand" "r"))
2815          (const_int 0)))
2816    (set (match_operand:DI 0 "register_operand" "=r")
2817         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
2818   ""
2819   "bics\\t%w0, %w2, %w1"
2820   [(set_attr "type" "logics_reg")]
2823 (define_insn "*<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
2824   [(set (match_operand:GPI 0 "register_operand" "=r")
2825         (LOGICAL:GPI (not:GPI
2826                       (SHIFT:GPI
2827                        (match_operand:GPI 1 "register_operand" "r")
2828                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2829                      (match_operand:GPI 3 "register_operand" "r")))]
2830   ""
2831   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
2832   [(set_attr "type" "logics_shift_imm")]
2835 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
2836   [(set (reg:CC_NZ CC_REGNUM)
2837         (compare:CC_NZ
2838          (and:GPI (not:GPI
2839                    (SHIFT:GPI
2840                     (match_operand:GPI 1 "register_operand" "r")
2841                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2842                   (match_operand:GPI 3 "register_operand" "r"))
2843          (const_int 0)))
2844    (set (match_operand:GPI 0 "register_operand" "=r")
2845         (and:GPI (not:GPI
2846                   (SHIFT:GPI
2847                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
2848   ""
2849   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
2850   [(set_attr "type" "logics_shift_imm")]
2853 ;; zero_extend version of above
2854 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
2855   [(set (reg:CC_NZ CC_REGNUM)
2856         (compare:CC_NZ
2857          (and:SI (not:SI
2858                   (SHIFT:SI
2859                    (match_operand:SI 1 "register_operand" "r")
2860                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
2861                  (match_operand:SI 3 "register_operand" "r"))
2862          (const_int 0)))
2863    (set (match_operand:DI 0 "register_operand" "=r")
2864         (zero_extend:DI (and:SI
2865                          (not:SI
2866                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
2867   ""
2868   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
2869   [(set_attr "type" "logics_shift_imm")]
2872 (define_insn "clz<mode>2"
2873   [(set (match_operand:GPI 0 "register_operand" "=r")
2874         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
2875   ""
2876   "clz\\t%<w>0, %<w>1"
2877   [(set_attr "type" "clz")]
2880 (define_expand "ffs<mode>2"
2881   [(match_operand:GPI 0 "register_operand")
2882    (match_operand:GPI 1 "register_operand")]
2883   ""
2884   {
2885     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
2886     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
2888     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
2889     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
2890     emit_insn (gen_csinc3<mode>_insn (operands[0], x, ccreg, operands[0], const0_rtx));
2891     DONE;
2892   }
2895 (define_insn "clrsb<mode>2"
2896   [(set (match_operand:GPI 0 "register_operand" "=r")
2897         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
2898   ""
2899   "cls\\t%<w>0, %<w>1"
2900   [(set_attr "type" "clz")]
2903 (define_insn "rbit<mode>2"
2904   [(set (match_operand:GPI 0 "register_operand" "=r")
2905         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
2906   ""
2907   "rbit\\t%<w>0, %<w>1"
2908   [(set_attr "type" "rbit")]
2911 (define_expand "ctz<mode>2"
2912   [(match_operand:GPI 0 "register_operand")
2913    (match_operand:GPI 1 "register_operand")]
2914   ""
2915   {
2916     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
2917     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
2918     DONE;
2919   }
2922 (define_insn "*and<mode>3nr_compare0"
2923   [(set (reg:CC_NZ CC_REGNUM)
2924         (compare:CC_NZ
2925          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
2926                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
2927          (const_int 0)))]
2928   ""
2929   "tst\\t%<w>0, %<w>1"
2930   [(set_attr "type" "logics_reg")]
2933 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
2934   [(set (reg:CC_NZ CC_REGNUM)
2935         (compare:CC_NZ
2936          (and:GPI (SHIFT:GPI
2937                    (match_operand:GPI 0 "register_operand" "r")
2938                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2939                   (match_operand:GPI 2 "register_operand" "r"))
2940         (const_int 0)))]
2941   ""
2942   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
2943   [(set_attr "type" "logics_shift_imm")]
2946 ;; -------------------------------------------------------------------
2947 ;; Shifts
2948 ;; -------------------------------------------------------------------
2950 (define_expand "<optab><mode>3"
2951   [(set (match_operand:GPI 0 "register_operand")
2952         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
2953                     (match_operand:QI 2 "nonmemory_operand")))]
2954   ""
2955   {
2956     if (CONST_INT_P (operands[2]))
2957       {
2958         operands[2] = GEN_INT (INTVAL (operands[2])
2959                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2961         if (operands[2] == const0_rtx)
2962           {
2963             emit_insn (gen_mov<mode> (operands[0], operands[1]));
2964             DONE;
2965           }
2966       }
2967   }
2970 (define_expand "ashl<mode>3"
2971   [(set (match_operand:SHORT 0 "register_operand")
2972         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
2973                       (match_operand:QI 2 "nonmemory_operand")))]
2974   ""
2975   {
2976     if (CONST_INT_P (operands[2]))
2977       {
2978         operands[2] = GEN_INT (INTVAL (operands[2])
2979                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2981         if (operands[2] == const0_rtx)
2982           {
2983             emit_insn (gen_mov<mode> (operands[0], operands[1]));
2984             DONE;
2985           }
2986       }
2987   }
2990 (define_expand "rotr<mode>3"
2991   [(set (match_operand:GPI 0 "register_operand")
2992         (rotatert:GPI (match_operand:GPI 1 "register_operand")
2993                       (match_operand:QI 2 "nonmemory_operand")))]
2994   ""
2995   {
2996     if (CONST_INT_P (operands[2]))
2997       {
2998         operands[2] = GEN_INT (INTVAL (operands[2])
2999                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3001         if (operands[2] == const0_rtx)
3002           {
3003             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3004             DONE;
3005           }
3006       }
3007   }
3010 (define_expand "rotl<mode>3"
3011   [(set (match_operand:GPI 0 "register_operand")
3012         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3013                       (match_operand:QI 2 "nonmemory_operand")))]
3014   ""
3015   {
3016     /* (SZ - cnt) % SZ == -cnt % SZ */
3017     if (CONST_INT_P (operands[2]))
3018       {
3019         operands[2] = GEN_INT ((-INTVAL (operands[2]))
3020                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3021         if (operands[2] == const0_rtx)
3022           {
3023             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3024             DONE;
3025           }
3026       }
3027     else
3028       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3029                                         NULL_RTX, 1);
3030   }
3033 ;; Logical left shift using SISD or Integer instruction
3034 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3035   [(set (match_operand:GPI 0 "register_operand" "=w,w,r")
3036         (ashift:GPI
3037           (match_operand:GPI 1 "register_operand" "w,w,r")
3038           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,w,rUs<cmode>")))]
3039   ""
3040   "@
3041    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3042    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
3043    lsl\t%<w>0, %<w>1, %<w>2"
3044   [(set_attr "simd" "yes,yes,no")
3045    (set_attr "type" "neon_shift_imm<q>, neon_shift_reg<q>,shift_reg")]
3048 ;; Logical right shift using SISD or Integer instruction
3049 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3050   [(set (match_operand:GPI 0 "register_operand" "=w,w,r")
3051         (lshiftrt:GPI
3052           (match_operand:GPI 1 "register_operand" "w,w,r")
3053           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,w,rUs<cmode>")))]
3054   ""
3055   "@
3056    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3057    #
3058    lsr\t%<w>0, %<w>1, %<w>2"
3059   [(set_attr "simd" "yes,yes,no")
3060    (set_attr "type" "neon_shift_imm<q>,neon_shift_reg<q>,shift_reg")]
3063 (define_split
3064   [(set (match_operand:DI 0 "aarch64_simd_register")
3065         (lshiftrt:DI
3066            (match_operand:DI 1 "aarch64_simd_register")
3067            (match_operand:QI 2 "aarch64_simd_register")))]
3068   "TARGET_SIMD && reload_completed"
3069   [(set (match_dup 2)
3070         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3071    (set (match_dup 0)
3072         (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_SISD_USHL))]
3073   ""
3076 (define_split
3077   [(set (match_operand:SI 0 "aarch64_simd_register")
3078         (lshiftrt:SI
3079            (match_operand:SI 1 "aarch64_simd_register")
3080            (match_operand:QI 2 "aarch64_simd_register")))]
3081   "TARGET_SIMD && reload_completed"
3082   [(set (match_dup 2)
3083         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3084    (set (match_dup 0)
3085         (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_USHL_2S))]
3086   ""
3089 ;; Arithmetic right shift using SISD or Integer instruction
3090 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
3091   [(set (match_operand:GPI 0 "register_operand" "=w,&w,&w,r")
3092         (ashiftrt:GPI
3093           (match_operand:GPI 1 "register_operand" "w,w,w,r")
3094           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,w,0,rUs<cmode>")))]
3095   ""
3096   "@
3097    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3098    #
3099    #
3100    asr\t%<w>0, %<w>1, %<w>2"
3101   [(set_attr "simd" "yes,yes,yes,no")
3102    (set_attr "type" "neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>,shift_reg")]
3105 (define_split
3106   [(set (match_operand:DI 0 "aarch64_simd_register")
3107         (ashiftrt:DI
3108            (match_operand:DI 1 "aarch64_simd_register")
3109            (match_operand:QI 2 "aarch64_simd_register")))]
3110   "TARGET_SIMD && reload_completed"
3111   [(set (match_dup 3)
3112         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3113    (set (match_dup 0)
3114         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
3116   operands[3] = gen_lowpart (QImode, operands[0]);
3120 (define_split
3121   [(set (match_operand:SI 0 "aarch64_simd_register")
3122         (ashiftrt:SI
3123            (match_operand:SI 1 "aarch64_simd_register")
3124            (match_operand:QI 2 "aarch64_simd_register")))]
3125   "TARGET_SIMD && reload_completed"
3126   [(set (match_dup 3)
3127         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3128    (set (match_dup 0)
3129         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
3131   operands[3] = gen_lowpart (QImode, operands[0]);
3135 (define_insn "*aarch64_sisd_ushl"
3136   [(set (match_operand:DI 0 "register_operand" "=w")
3137         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
3138                     (match_operand:QI 2 "register_operand" "w")]
3139                    UNSPEC_SISD_USHL))]
3140   "TARGET_SIMD"
3141   "ushl\t%d0, %d1, %d2"
3142   [(set_attr "simd" "yes")
3143    (set_attr "type" "neon_shift_reg")]
3146 (define_insn "*aarch64_ushl_2s"
3147   [(set (match_operand:SI 0 "register_operand" "=w")
3148         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
3149                     (match_operand:QI 2 "register_operand" "w")]
3150                    UNSPEC_USHL_2S))]
3151   "TARGET_SIMD"
3152   "ushl\t%0.2s, %1.2s, %2.2s"
3153   [(set_attr "simd" "yes")
3154    (set_attr "type" "neon_shift_reg")]
3157 (define_insn "*aarch64_sisd_sshl"
3158   [(set (match_operand:DI 0 "register_operand" "=w")
3159         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
3160                     (match_operand:QI 2 "register_operand" "w")]
3161                    UNSPEC_SISD_SSHL))]
3162   "TARGET_SIMD"
3163   "sshl\t%d0, %d1, %d2"
3164   [(set_attr "simd" "yes")
3165    (set_attr "type" "neon_shift_reg")]
3168 (define_insn "*aarch64_sshl_2s"
3169   [(set (match_operand:SI 0 "register_operand" "=w")
3170         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
3171                     (match_operand:QI 2 "register_operand" "w")]
3172                    UNSPEC_SSHL_2S))]
3173   "TARGET_SIMD"
3174   "sshl\t%0.2s, %1.2s, %2.2s"
3175   [(set_attr "simd" "yes")
3176    (set_attr "type" "neon_shift_reg")]
3179 (define_insn "*aarch64_sisd_neg_qi"
3180   [(set (match_operand:QI 0 "register_operand" "=w")
3181         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
3182                    UNSPEC_SISD_NEG))]
3183   "TARGET_SIMD"
3184   "neg\t%d0, %d1"
3185   [(set_attr "simd" "yes")
3186    (set_attr "type" "neon_neg")]
3189 ;; Rotate right
3190 (define_insn "*ror<mode>3_insn"
3191   [(set (match_operand:GPI 0 "register_operand" "=r")
3192         (rotatert:GPI
3193           (match_operand:GPI 1 "register_operand" "r")
3194           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "rUs<cmode>")))]
3195   ""
3196   "ror\\t%<w>0, %<w>1, %<w>2"
3197   [(set_attr "type" "shift_reg")]
3200 ;; zero_extend version of above
3201 (define_insn "*<optab>si3_insn_uxtw"
3202   [(set (match_operand:DI 0 "register_operand" "=r")
3203         (zero_extend:DI (SHIFT:SI
3204          (match_operand:SI 1 "register_operand" "r")
3205          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "rUss"))))]
3206   ""
3207   "<shift>\\t%w0, %w1, %w2"
3208   [(set_attr "type" "shift_reg")]
3211 (define_insn "*ashl<mode>3_insn"
3212   [(set (match_operand:SHORT 0 "register_operand" "=r")
3213         (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
3214                       (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "rUss")))]
3215   ""
3216   "lsl\\t%<w>0, %<w>1, %<w>2"
3217   [(set_attr "type" "shift_reg")]
3220 (define_insn "*<optab><mode>3_insn"
3221   [(set (match_operand:SHORT 0 "register_operand" "=r")
3222         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
3223                       (match_operand 2 "const_int_operand" "n")))]
3224   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
3226   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
3227   return "<bfshift>\t%w0, %w1, %2, %3";
3229   [(set_attr "type" "bfm")]
3232 (define_insn "*extr<mode>5_insn"
3233   [(set (match_operand:GPI 0 "register_operand" "=r")
3234         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3235                              (match_operand 3 "const_int_operand" "n"))
3236                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
3237                                (match_operand 4 "const_int_operand" "n"))))]
3238   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
3239    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
3240   "extr\\t%<w>0, %<w>1, %<w>2, %4"
3241   [(set_attr "type" "shift_imm")]
3244 ;; zero_extend version of the above
3245 (define_insn "*extrsi5_insn_uxtw"
3246   [(set (match_operand:DI 0 "register_operand" "=r")
3247         (zero_extend:DI
3248          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
3249                             (match_operand 3 "const_int_operand" "n"))
3250                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
3251                               (match_operand 4 "const_int_operand" "n")))))]
3252   "UINTVAL (operands[3]) < 32 &&
3253    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
3254   "extr\\t%w0, %w1, %w2, %4"
3255   [(set_attr "type" "shift_imm")]
3258 (define_insn "*ror<mode>3_insn"
3259   [(set (match_operand:GPI 0 "register_operand" "=r")
3260         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
3261                     (match_operand 2 "const_int_operand" "n")))]
3262   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
3264   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
3265   return "ror\\t%<w>0, %<w>1, %3";
3267   [(set_attr "type" "shift_imm")]
3270 ;; zero_extend version of the above
3271 (define_insn "*rorsi3_insn_uxtw"
3272   [(set (match_operand:DI 0 "register_operand" "=r")
3273         (zero_extend:DI
3274          (rotate:SI (match_operand:SI 1 "register_operand" "r")
3275                     (match_operand 2 "const_int_operand" "n"))))]
3276   "UINTVAL (operands[2]) < 32"
3278   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
3279   return "ror\\t%w0, %w1, %3";
3281   [(set_attr "type" "shift_imm")]
3284 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
3285   [(set (match_operand:GPI 0 "register_operand" "=r")
3286         (ANY_EXTEND:GPI
3287          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
3288                        (match_operand 2 "const_int_operand" "n"))))]
3289   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
3291   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
3292   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
3294   [(set_attr "type" "bfm")]
3297 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
3298   [(set (match_operand:GPI 0 "register_operand" "=r")
3299         (zero_extend:GPI
3300          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
3301                          (match_operand 2 "const_int_operand" "n"))))]
3302   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
3304   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
3305   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
3307   [(set_attr "type" "bfm")]
3310 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
3311   [(set (match_operand:GPI 0 "register_operand" "=r")
3312         (sign_extend:GPI
3313          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
3314                          (match_operand 2 "const_int_operand" "n"))))]
3315   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
3317   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
3318   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
3320   [(set_attr "type" "bfm")]
3323 ;; -------------------------------------------------------------------
3324 ;; Bitfields
3325 ;; -------------------------------------------------------------------
3327 (define_expand "<optab>"
3328   [(set (match_operand:DI 0 "register_operand" "=r")
3329         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand" "r")
3330                         (match_operand 2 "const_int_operand" "n")
3331                         (match_operand 3 "const_int_operand" "n")))]
3332   ""
3333   ""
3336 (define_insn "*<optab><mode>"
3337   [(set (match_operand:GPI 0 "register_operand" "=r")
3338         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
3339                          (match_operand 2 "const_int_operand" "n")
3340                          (match_operand 3 "const_int_operand" "n")))]
3341   ""
3342   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
3343   [(set_attr "type" "bfm")]
3346 ;; Bitfield Insert (insv)
3347 (define_expand "insv<mode>"
3348   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
3349                           (match_operand 1 "const_int_operand")
3350                           (match_operand 2 "const_int_operand"))
3351         (match_operand:GPI 3 "general_operand"))]
3352   ""
3354   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
3355   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
3356   rtx value = operands[3];
3358   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
3359     FAIL;
3361   if (CONST_INT_P (value))
3362     {
3363       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
3365       /* Prefer AND/OR for inserting all zeros or all ones.  */
3366       if ((UINTVAL (value) & mask) == 0
3367            || (UINTVAL (value) & mask) == mask)
3368         FAIL;
3370       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
3371       if (width == 16 && (pos % 16) == 0)
3372         DONE;
3373     }
3374   operands[3] = force_reg (<MODE>mode, value);
3377 (define_insn "*insv_reg<mode>"
3378   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
3379                           (match_operand 1 "const_int_operand" "n")
3380                           (match_operand 2 "const_int_operand" "n"))
3381         (match_operand:GPI 3 "register_operand" "r"))]
3382   "!(UINTVAL (operands[1]) == 0
3383      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
3384          > GET_MODE_BITSIZE (<MODE>mode)))"
3385   "bfi\\t%<w>0, %<w>3, %2, %1"
3386   [(set_attr "type" "bfm")]
3389 (define_insn "*extr_insv_lower_reg<mode>"
3390   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
3391                           (match_operand 1 "const_int_operand" "n")
3392                           (const_int 0))
3393         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "+r")
3394                           (match_dup 1)
3395                           (match_operand 3 "const_int_operand" "n")))]
3396   "!(UINTVAL (operands[1]) == 0
3397      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
3398          > GET_MODE_BITSIZE (<MODE>mode)))"
3399   "bfxil\\t%<w>0, %<w>2, %3, %1"
3400   [(set_attr "type" "bfm")]
3403 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
3404   [(set (match_operand:GPI 0 "register_operand" "=r")
3405         (ashift:GPI (ANY_EXTEND:GPI
3406                      (match_operand:ALLX 1 "register_operand" "r"))
3407                     (match_operand 2 "const_int_operand" "n")))]
3408   "UINTVAL (operands[2]) < <GPI:sizen>"
3410   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
3411               ? GEN_INT (<ALLX:sizen>)
3412               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
3413   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
3415   [(set_attr "type" "bfm")]
3418 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
3420 (define_insn "*andim_ashift<mode>_bfiz"
3421   [(set (match_operand:GPI 0 "register_operand" "=r")
3422         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3423                              (match_operand 2 "const_int_operand" "n"))
3424                  (match_operand 3 "const_int_operand" "n")))]
3425   "exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1) >= 0
3426    && (INTVAL (operands[3]) & ((1 << INTVAL (operands[2])) - 1)) == 0"
3427   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
3428   [(set_attr "type" "bfm")]
3431 (define_insn "bswap<mode>2"
3432   [(set (match_operand:GPI 0 "register_operand" "=r")
3433         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
3434   ""
3435   "rev\\t%<w>0, %<w>1"
3436   [(set_attr "type" "rev")]
3439 (define_insn "bswaphi2"
3440   [(set (match_operand:HI 0 "register_operand" "=r")
3441         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
3442   ""
3443   "rev16\\t%w0, %w1"
3444   [(set_attr "type" "rev")]
3447 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
3448 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
3449 ;; each valid permutation.
3451 (define_insn "rev16<mode>2"
3452   [(set (match_operand:GPI 0 "register_operand" "=r")
3453         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3454                                       (const_int 8))
3455                           (match_operand:GPI 3 "const_int_operand" "n"))
3456                  (and:GPI (lshiftrt:GPI (match_dup 1)
3457                                         (const_int 8))
3458                           (match_operand:GPI 2 "const_int_operand" "n"))))]
3459   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
3460    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
3461   "rev16\\t%<w>0, %<w>1"
3462   [(set_attr "type" "rev")]
3465 (define_insn "rev16<mode>2_alt"
3466   [(set (match_operand:GPI 0 "register_operand" "=r")
3467         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
3468                                         (const_int 8))
3469                           (match_operand:GPI 2 "const_int_operand" "n"))
3470                  (and:GPI (ashift:GPI (match_dup 1)
3471                                       (const_int 8))
3472                           (match_operand:GPI 3 "const_int_operand" "n"))))]
3473   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
3474    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
3475   "rev16\\t%<w>0, %<w>1"
3476   [(set_attr "type" "rev")]
3479 ;; zero_extend version of above
3480 (define_insn "*bswapsi2_uxtw"
3481   [(set (match_operand:DI 0 "register_operand" "=r")
3482         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
3483   ""
3484   "rev\\t%w0, %w1"
3485   [(set_attr "type" "rev")]
3488 ;; -------------------------------------------------------------------
3489 ;; Floating-point intrinsics
3490 ;; -------------------------------------------------------------------
3492 ;; frint floating-point round to integral standard patterns.
3493 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
3495 (define_insn "<frint_pattern><mode>2"
3496   [(set (match_operand:GPF 0 "register_operand" "=w")
3497         (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
3498          FRINT))]
3499   "TARGET_FLOAT"
3500   "frint<frint_suffix>\\t%<s>0, %<s>1"
3501   [(set_attr "type" "f_rint<s>")]
3504 ;; frcvt floating-point round to integer and convert standard patterns.
3505 ;; Expands to lbtrunc, lceil, lfloor, lround.
3506 (define_insn "l<fcvt_pattern><su_optab><GPF:mode><GPI:mode>2"
3507   [(set (match_operand:GPI 0 "register_operand" "=r")
3508         (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
3509                       FCVT)))]
3510   "TARGET_FLOAT"
3511   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF:s>1"
3512   [(set_attr "type" "f_cvtf2i")]
3515 ;; fma - no throw
3517 (define_insn "fma<mode>4"
3518   [(set (match_operand:GPF 0 "register_operand" "=w")
3519         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
3520                  (match_operand:GPF 2 "register_operand" "w")
3521                  (match_operand:GPF 3 "register_operand" "w")))]
3522   "TARGET_FLOAT"
3523   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
3524   [(set_attr "type" "fmac<s>")]
3527 (define_insn "fnma<mode>4"
3528   [(set (match_operand:GPF 0 "register_operand" "=w")
3529         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
3530                  (match_operand:GPF 2 "register_operand" "w")
3531                  (match_operand:GPF 3 "register_operand" "w")))]
3532   "TARGET_FLOAT"
3533   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
3534   [(set_attr "type" "fmac<s>")]
3537 (define_insn "fms<mode>4"
3538   [(set (match_operand:GPF 0 "register_operand" "=w")
3539         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
3540                  (match_operand:GPF 2 "register_operand" "w")
3541                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
3542   "TARGET_FLOAT"
3543   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
3544   [(set_attr "type" "fmac<s>")]
3547 (define_insn "fnms<mode>4"
3548   [(set (match_operand:GPF 0 "register_operand" "=w")
3549         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
3550                  (match_operand:GPF 2 "register_operand" "w")
3551                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
3552   "TARGET_FLOAT"
3553   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
3554   [(set_attr "type" "fmac<s>")]
3557 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
3558 (define_insn "*fnmadd<mode>4"
3559   [(set (match_operand:GPF 0 "register_operand" "=w")
3560         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
3561                           (match_operand:GPF 2 "register_operand" "w")
3562                           (match_operand:GPF 3 "register_operand" "w"))))]
3563   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
3564   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
3565   [(set_attr "type" "fmac<s>")]
3568 ;; -------------------------------------------------------------------
3569 ;; Floating-point conversions
3570 ;; -------------------------------------------------------------------
3572 (define_insn "extendsfdf2"
3573   [(set (match_operand:DF 0 "register_operand" "=w")
3574         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
3575   "TARGET_FLOAT"
3576   "fcvt\\t%d0, %s1"
3577   [(set_attr "type" "f_cvt")]
3580 (define_insn "truncdfsf2"
3581   [(set (match_operand:SF 0 "register_operand" "=w")
3582         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
3583   "TARGET_FLOAT"
3584   "fcvt\\t%s0, %d1"
3585   [(set_attr "type" "f_cvt")]
3588 (define_insn "fix_trunc<GPF:mode><GPI:mode>2"
3589   [(set (match_operand:GPI 0 "register_operand" "=r")
3590         (fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
3591   "TARGET_FLOAT"
3592   "fcvtzs\\t%<GPI:w>0, %<GPF:s>1"
3593   [(set_attr "type" "f_cvtf2i")]
3596 (define_insn "fixuns_trunc<GPF:mode><GPI:mode>2"
3597   [(set (match_operand:GPI 0 "register_operand" "=r")
3598         (unsigned_fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
3599   "TARGET_FLOAT"
3600   "fcvtzu\\t%<GPI:w>0, %<GPF:s>1"
3601   [(set_attr "type" "f_cvtf2i")]
3604 (define_insn "<optab><fcvt_target><GPF:mode>2"
3605   [(set (match_operand:GPF 0 "register_operand" "=w,w")
3606         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
3607   ""
3608   "@
3609    <su_optab>cvtf\t%<GPF:s>0, %<s>1
3610    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
3611   [(set_attr "simd" "yes,no")
3612    (set_attr "fp" "no,yes")
3613    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
3616 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
3617   [(set (match_operand:GPF 0 "register_operand" "=w")
3618         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
3619   "TARGET_FLOAT"
3620   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
3621   [(set_attr "type" "f_cvti2f")]
3624 ;; -------------------------------------------------------------------
3625 ;; Floating-point arithmetic
3626 ;; -------------------------------------------------------------------
3628 (define_insn "add<mode>3"
3629   [(set (match_operand:GPF 0 "register_operand" "=w")
3630         (plus:GPF
3631          (match_operand:GPF 1 "register_operand" "w")
3632          (match_operand:GPF 2 "register_operand" "w")))]
3633   "TARGET_FLOAT"
3634   "fadd\\t%<s>0, %<s>1, %<s>2"
3635   [(set_attr "type" "fadd<s>")]
3638 (define_insn "sub<mode>3"
3639   [(set (match_operand:GPF 0 "register_operand" "=w")
3640         (minus:GPF
3641          (match_operand:GPF 1 "register_operand" "w")
3642          (match_operand:GPF 2 "register_operand" "w")))]
3643   "TARGET_FLOAT"
3644   "fsub\\t%<s>0, %<s>1, %<s>2"
3645   [(set_attr "type" "fadd<s>")]
3648 (define_insn "mul<mode>3"
3649   [(set (match_operand:GPF 0 "register_operand" "=w")
3650         (mult:GPF
3651          (match_operand:GPF 1 "register_operand" "w")
3652          (match_operand:GPF 2 "register_operand" "w")))]
3653   "TARGET_FLOAT"
3654   "fmul\\t%<s>0, %<s>1, %<s>2"
3655   [(set_attr "type" "fmul<s>")]
3658 (define_insn "*fnmul<mode>3"
3659   [(set (match_operand:GPF 0 "register_operand" "=w")
3660         (mult:GPF
3661                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
3662                  (match_operand:GPF 2 "register_operand" "w")))]
3663   "TARGET_FLOAT"
3664   "fnmul\\t%<s>0, %<s>1, %<s>2"
3665   [(set_attr "type" "fmul<s>")]
3668 (define_insn "div<mode>3"
3669   [(set (match_operand:GPF 0 "register_operand" "=w")
3670         (div:GPF
3671          (match_operand:GPF 1 "register_operand" "w")
3672          (match_operand:GPF 2 "register_operand" "w")))]
3673   "TARGET_FLOAT"
3674   "fdiv\\t%<s>0, %<s>1, %<s>2"
3675   [(set_attr "type" "fdiv<s>")]
3678 (define_insn "neg<mode>2"
3679   [(set (match_operand:GPF 0 "register_operand" "=w")
3680         (neg:GPF (match_operand:GPF 1 "register_operand" "w")))]
3681   "TARGET_FLOAT"
3682   "fneg\\t%<s>0, %<s>1"
3683   [(set_attr "type" "ffarith<s>")]
3686 (define_insn "sqrt<mode>2"
3687   [(set (match_operand:GPF 0 "register_operand" "=w")
3688         (sqrt:GPF (match_operand:GPF 1 "register_operand" "w")))]
3689   "TARGET_FLOAT"
3690   "fsqrt\\t%<s>0, %<s>1"
3691   [(set_attr "type" "fsqrt<s>")]
3694 (define_insn "abs<mode>2"
3695   [(set (match_operand:GPF 0 "register_operand" "=w")
3696         (abs:GPF (match_operand:GPF 1 "register_operand" "w")))]
3697   "TARGET_FLOAT"
3698   "fabs\\t%<s>0, %<s>1"
3699   [(set_attr "type" "ffarith<s>")]
3702 ;; Given that smax/smin do not specify the result when either input is NaN,
3703 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
3704 ;; for smin.
3706 (define_insn "smax<mode>3"
3707   [(set (match_operand:GPF 0 "register_operand" "=w")
3708         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
3709                   (match_operand:GPF 2 "register_operand" "w")))]
3710   "TARGET_FLOAT"
3711   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
3712   [(set_attr "type" "f_minmax<s>")]
3715 (define_insn "smin<mode>3"
3716   [(set (match_operand:GPF 0 "register_operand" "=w")
3717         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
3718                   (match_operand:GPF 2 "register_operand" "w")))]
3719   "TARGET_FLOAT"
3720   "fminnm\\t%<s>0, %<s>1, %<s>2"
3721   [(set_attr "type" "f_minmax<s>")]
3724 ;; -------------------------------------------------------------------
3725 ;; Reload support
3726 ;; -------------------------------------------------------------------
3728 (define_expand "aarch64_reload_mov<mode>"
3729   [(set (match_operand:TX 0 "register_operand" "=w")
3730         (match_operand:TX 1 "register_operand" "w"))
3731    (clobber (match_operand:DI 2 "register_operand" "=&r"))
3732   ]
3733   ""
3734   {
3735     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
3736     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
3737     gen_aarch64_movtilow_tilow (op0, op1);
3738     gen_aarch64_movdi_tihigh (operands[2], op1);
3739     gen_aarch64_movtihigh_di (op0, operands[2]);
3740     DONE;
3741   }
3744 ;; The following secondary reload helpers patterns are invoked
3745 ;; after or during reload as we don't want these patterns to start
3746 ;; kicking in during the combiner.
3748 (define_insn "aarch64_movdi_<mode>low"
3749   [(set (match_operand:DI 0 "register_operand" "=r")
3750         (truncate:DI (match_operand:TX 1 "register_operand" "w")))]
3751   "reload_completed || reload_in_progress"
3752   "fmov\\t%x0, %d1"
3753   [(set_attr "type" "f_mrc")
3754    (set_attr "length" "4")
3755   ])
3757 (define_insn "aarch64_movdi_<mode>high"
3758   [(set (match_operand:DI 0 "register_operand" "=r")
3759         (truncate:DI
3760           (lshiftrt:TX (match_operand:TX 1 "register_operand" "w")
3761                        (const_int 64))))]
3762   "reload_completed || reload_in_progress"
3763   "fmov\\t%x0, %1.d[1]"
3764   [(set_attr "type" "f_mrc")
3765    (set_attr "length" "4")
3766   ])
3768 (define_insn "aarch64_mov<mode>high_di"
3769   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
3770                          (const_int 64) (const_int 64))
3771         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
3772   "reload_completed || reload_in_progress"
3773   "fmov\\t%0.d[1], %x1"
3774   [(set_attr "type" "f_mcr")
3775    (set_attr "length" "4")
3776   ])
3778 (define_insn "aarch64_mov<mode>low_di"
3779   [(set (match_operand:TX 0 "register_operand" "=w")
3780         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
3781   "reload_completed || reload_in_progress"
3782   "fmov\\t%d0, %x1"
3783   [(set_attr "type" "f_mcr")
3784    (set_attr "length" "4")
3785   ])
3787 (define_insn "aarch64_movtilow_tilow"
3788   [(set (match_operand:TI 0 "register_operand" "=w")
3789         (zero_extend:TI 
3790           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
3791   "reload_completed || reload_in_progress"
3792   "fmov\\t%d0, %d1"
3793   [(set_attr "type" "fmov")
3794    (set_attr "length" "4")
3795   ])
3797 ;; There is a deliberate reason why the parameters of high and lo_sum's
3798 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
3799 ;; and lo_sum's to be used with the labels defining the jump tables in
3800 ;; rodata section.
3802 (define_expand "add_losym"
3803   [(set (match_operand 0 "register_operand" "=r")
3804         (lo_sum (match_operand 1 "register_operand" "r")
3805                 (match_operand 2 "aarch64_valid_symref" "S")))]
3806   ""
3808   enum machine_mode mode = GET_MODE (operands[0]);
3810   emit_insn ((mode == DImode
3811               ? gen_add_losym_di
3812               : gen_add_losym_si) (operands[0],
3813                                    operands[1],
3814                                    operands[2]));
3815   DONE;
3818 (define_insn "add_losym_<mode>"
3819   [(set (match_operand:P 0 "register_operand" "=r")
3820         (lo_sum:P (match_operand:P 1 "register_operand" "r")
3821                   (match_operand 2 "aarch64_valid_symref" "S")))]
3822   ""
3823   "add\\t%<w>0, %<w>1, :lo12:%a2"
3824   [(set_attr "type" "alu_imm")]
3827 (define_insn "ldr_got_small_<mode>"
3828   [(set (match_operand:PTR 0 "register_operand" "=r")
3829         (unspec:PTR [(mem:PTR (lo_sum:PTR
3830                               (match_operand:PTR 1 "register_operand" "r")
3831                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
3832                     UNSPEC_GOTSMALLPIC))]
3833   ""
3834   "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
3835   [(set_attr "type" "load1")]
3838 (define_insn "ldr_got_small_sidi"
3839   [(set (match_operand:DI 0 "register_operand" "=r")
3840         (zero_extend:DI
3841          (unspec:SI [(mem:SI (lo_sum:DI
3842                              (match_operand:DI 1 "register_operand" "r")
3843                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
3844                     UNSPEC_GOTSMALLPIC)))]
3845   "TARGET_ILP32"
3846   "ldr\\t%w0, [%1, #:got_lo12:%a2]"
3847   [(set_attr "type" "load1")]
3850 (define_insn "ldr_got_tiny"
3851   [(set (match_operand:DI 0 "register_operand" "=r")
3852         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
3853                    UNSPEC_GOTTINYPIC))]
3854   ""
3855   "ldr\\t%0, %L1"
3856   [(set_attr "type" "load1")]
3859 (define_insn "aarch64_load_tp_hard"
3860   [(set (match_operand:DI 0 "register_operand" "=r")
3861         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
3862   ""
3863   "mrs\\t%0, tpidr_el0"
3864   [(set_attr "type" "mrs")]
3867 ;; The TLS ABI specifically requires that the compiler does not schedule
3868 ;; instructions in the TLS stubs, in order to enable linker relaxation.
3869 ;; Therefore we treat the stubs as an atomic sequence.
3870 (define_expand "tlsgd_small"
3871  [(parallel [(set (match_operand 0 "register_operand" "")
3872                   (call (mem:DI (match_dup 2)) (const_int 1)))
3873              (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
3874              (clobber (reg:DI LR_REGNUM))])]
3875  ""
3877   operands[2] = aarch64_tls_get_addr ();
3880 (define_insn "*tlsgd_small"
3881   [(set (match_operand 0 "register_operand" "")
3882         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
3883    (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
3884    (clobber (reg:DI LR_REGNUM))
3885   ]
3886   ""
3887   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
3888   [(set_attr "type" "call")
3889    (set_attr "length" "16")])
3891 (define_insn "tlsie_small_<mode>"
3892   [(set (match_operand:PTR 0 "register_operand" "=r")
3893         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
3894                    UNSPEC_GOTSMALLTLS))]
3895   ""
3896   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
3897   [(set_attr "type" "load1")
3898    (set_attr "length" "8")]
3901 (define_insn "tlsie_small_sidi"
3902   [(set (match_operand:DI 0 "register_operand" "=r")
3903         (zero_extend:DI
3904           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
3905                       UNSPEC_GOTSMALLTLS)))]
3906   ""
3907   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
3908   [(set_attr "type" "load1")
3909    (set_attr "length" "8")]
3912 (define_expand "tlsle_small"
3913   [(set (match_operand 0 "register_operand" "=r")
3914         (unspec [(match_operand 1 "register_operand" "r")
3915                    (match_operand 2 "aarch64_tls_le_symref" "S")]
3916                    UNSPEC_GOTSMALLTLS))]
3917   ""
3919   enum machine_mode mode = GET_MODE (operands[0]);
3920   emit_insn ((mode == DImode
3921               ? gen_tlsle_small_di
3922               : gen_tlsle_small_si) (operands[0],
3923                                      operands[1],
3924                                      operands[2]));
3925   DONE;
3928 (define_insn "tlsle_small_<mode>"
3929   [(set (match_operand:P 0 "register_operand" "=r")
3930         (unspec:P [(match_operand:P 1 "register_operand" "r")
3931                    (match_operand 2 "aarch64_tls_le_symref" "S")]
3932                    UNSPEC_GOTSMALLTLS))]
3933   ""
3934   "add\\t%<w>0, %<w>1, #%G2\;add\\t%<w>0, %<w>0, #%L2"
3935   [(set_attr "type" "alu_sreg")
3936    (set_attr "length" "8")]
3939 (define_insn "tlsdesc_small_<mode>"
3940   [(set (reg:PTR R0_REGNUM)
3941         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
3942                    UNSPEC_TLSDESC))
3943    (clobber (reg:DI LR_REGNUM))
3944    (clobber (reg:CC CC_REGNUM))
3945    (clobber (match_scratch:DI 1 "=r"))]
3946   "TARGET_TLS_DESC"
3947   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
3948   [(set_attr "type" "call")
3949    (set_attr "length" "16")])
3951 (define_insn "stack_tie"
3952   [(set (mem:BLK (scratch))
3953         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
3954                      (match_operand:DI 1 "register_operand" "rk")]
3955                     UNSPEC_PRLG_STK))]
3956   ""
3957   ""
3958   [(set_attr "length" "0")]
3961 ;; Named pattern for expanding thread pointer reference.
3962 (define_expand "get_thread_pointerdi"
3963   [(match_operand:DI 0 "register_operand" "=r")]
3964   ""
3966   rtx tmp = aarch64_load_tp (operands[0]);
3967   if (tmp != operands[0])
3968     emit_move_insn (operands[0], tmp);
3969   DONE;
3972 ;; Named patterns for stack smashing protection.
3973 (define_expand "stack_protect_set"
3974   [(match_operand 0 "memory_operand")
3975    (match_operand 1 "memory_operand")]
3976   ""
3978   enum machine_mode mode = GET_MODE (operands[0]);
3980   emit_insn ((mode == DImode
3981               ? gen_stack_protect_set_di
3982               : gen_stack_protect_set_si) (operands[0], operands[1]));
3983   DONE;
3986 (define_insn "stack_protect_set_<mode>"
3987   [(set (match_operand:PTR 0 "memory_operand" "=m")
3988         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
3989          UNSPEC_SP_SET))
3990    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
3991   ""
3992   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
3993   [(set_attr "length" "12")
3994    (set_attr "type" "multiple")])
3996 (define_expand "stack_protect_test"
3997   [(match_operand 0 "memory_operand")
3998    (match_operand 1 "memory_operand")
3999    (match_operand 2)]
4000   ""
4002   rtx result;
4003   enum machine_mode mode = GET_MODE (operands[0]);
4005   result = gen_reg_rtx(mode);
4007   emit_insn ((mode == DImode
4008               ? gen_stack_protect_test_di
4009               : gen_stack_protect_test_si) (result,
4010                                             operands[0],
4011                                             operands[1]));
4013   if (mode == DImode)
4014     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
4015                                     result, const0_rtx, operands[2]));
4016   else
4017     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
4018                                     result, const0_rtx, operands[2]));
4019   DONE;
4022 (define_insn "stack_protect_test_<mode>"
4023   [(set (match_operand:PTR 0 "register_operand")
4024         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
4025                      (match_operand:PTR 2 "memory_operand" "m")]
4026          UNSPEC_SP_TEST))
4027    (clobber (match_scratch:PTR 3 "=&r"))]
4028   ""
4029   "ldr\t%<w>3, %x1\;ldr\t%<w>0, %x2\;eor\t%<w>0, %<w>3, %<w>0"
4030   [(set_attr "length" "12")
4031    (set_attr "type" "multiple")])
4033 ;; Write Floating-point Control Register.
4034 (define_insn "set_fpcr"
4035   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
4036   ""
4037   "msr\\tfpcr, %0"
4038   [(set_attr "type" "mrs")])
4040 ;; Read Floating-point Control Register.
4041 (define_insn "get_fpcr"
4042   [(set (match_operand:SI 0 "register_operand" "=r")
4043         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
4044   ""
4045   "mrs\\t%0, fpcr"
4046   [(set_attr "type" "mrs")])
4048 ;; Write Floating-point Status Register.
4049 (define_insn "set_fpsr"
4050   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
4051   ""
4052   "msr\\tfpsr, %0"
4053   [(set_attr "type" "mrs")])
4055 ;; Read Floating-point Status Register.
4056 (define_insn "get_fpsr"
4057   [(set (match_operand:SI 0 "register_operand" "=r")
4058         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
4059   ""
4060   "mrs\\t%0, fpsr"
4061   [(set_attr "type" "mrs")])
4064 ;; AdvSIMD Stuff
4065 (include "aarch64-simd.md")
4067 ;; Atomic Operations
4068 (include "atomics.md")