gcc/
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blobb715f175de361d8cec3d0b93e18e42fa965b3298
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2015 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; Register numbers
22 (define_constants
23   [
24     (R0_REGNUM          0)
25     (R1_REGNUM          1)
26     (R2_REGNUM          2)
27     (R3_REGNUM          3)
28     (R4_REGNUM          4)
29     (R5_REGNUM          5)
30     (R6_REGNUM          6)
31     (R7_REGNUM          7)
32     (R8_REGNUM          8)
33     (R9_REGNUM          9)
34     (R10_REGNUM         10)
35     (R11_REGNUM         11)
36     (R12_REGNUM         12)
37     (R13_REGNUM         13)
38     (R14_REGNUM         14)
39     (R15_REGNUM         15)
40     (R16_REGNUM         16)
41     (IP0_REGNUM         16)
42     (R17_REGNUM         17)
43     (IP1_REGNUM         17)
44     (R18_REGNUM         18)
45     (R19_REGNUM         19)
46     (R20_REGNUM         20)
47     (R21_REGNUM         21)
48     (R22_REGNUM         22)
49     (R23_REGNUM         23)
50     (R24_REGNUM         24)
51     (R25_REGNUM         25)
52     (R26_REGNUM         26)
53     (R27_REGNUM         27)
54     (R28_REGNUM         28)
55     (R29_REGNUM         29)
56     (R30_REGNUM         30)
57     (LR_REGNUM          30)
58     (SP_REGNUM          31)
59     (V0_REGNUM          32)
60     (V15_REGNUM         47)
61     (V31_REGNUM         63)
62     (SFP_REGNUM         64)
63     (AP_REGNUM          65)
64     (CC_REGNUM          66)
65   ]
68 (define_c_enum "unspec" [
69     UNSPEC_CASESI
70     UNSPEC_CRC32B
71     UNSPEC_CRC32CB
72     UNSPEC_CRC32CH
73     UNSPEC_CRC32CW
74     UNSPEC_CRC32CX
75     UNSPEC_CRC32H
76     UNSPEC_CRC32W
77     UNSPEC_CRC32X
78     UNSPEC_URECPE
79     UNSPEC_FRECPE
80     UNSPEC_FRECPS
81     UNSPEC_FRECPX
82     UNSPEC_FRINTA
83     UNSPEC_FRINTI
84     UNSPEC_FRINTM
85     UNSPEC_FRINTN
86     UNSPEC_FRINTP
87     UNSPEC_FRINTX
88     UNSPEC_FRINTZ
89     UNSPEC_GOTSMALLPIC
90     UNSPEC_GOTSMALLTLS
91     UNSPEC_GOTTINYPIC
92     UNSPEC_LD1
93     UNSPEC_LD2
94     UNSPEC_LD2_DUP
95     UNSPEC_LD3
96     UNSPEC_LD3_DUP
97     UNSPEC_LD4
98     UNSPEC_LD4_DUP
99     UNSPEC_LD2_LANE
100     UNSPEC_LD3_LANE
101     UNSPEC_LD4_LANE
102     UNSPEC_MB
103     UNSPEC_NOP
104     UNSPEC_PRLG_STK
105     UNSPEC_RBIT
106     UNSPEC_SISD_NEG
107     UNSPEC_SISD_SSHL
108     UNSPEC_SISD_USHL
109     UNSPEC_SSHL_2S
110     UNSPEC_ST1
111     UNSPEC_ST2
112     UNSPEC_ST3
113     UNSPEC_ST4
114     UNSPEC_ST2_LANE
115     UNSPEC_ST3_LANE
116     UNSPEC_ST4_LANE
117     UNSPEC_TLS
118     UNSPEC_TLSDESC
119     UNSPEC_USHL_2S
120     UNSPEC_VSTRUCTDUMMY
121     UNSPEC_SP_SET
122     UNSPEC_SP_TEST
125 (define_c_enum "unspecv" [
126     UNSPECV_EH_RETURN           ; Represent EH_RETURN
127     UNSPECV_GET_FPCR            ; Represent fetch of FPCR content.
128     UNSPECV_SET_FPCR            ; Represent assign of FPCR content.
129     UNSPECV_GET_FPSR            ; Represent fetch of FPSR content.
130     UNSPECV_SET_FPSR            ; Represent assign of FPSR content.
131   ]
134 ;; If further include files are added the defintion of MD_INCLUDES
135 ;; must be updated.
137 (include "constraints.md")
138 (include "predicates.md")
139 (include "iterators.md")
141 ;; -------------------------------------------------------------------
142 ;; Instruction types and attributes
143 ;; -------------------------------------------------------------------
145 ; The "type" attribute is is included here from AArch32 backend to be able
146 ; to share pipeline descriptions.
147 (include "../arm/types.md")
149 ;; It is important to set the fp or simd attributes to yes when a pattern
150 ;; alternative uses the FP or SIMD register files, usually signified by use of
151 ;; the 'w' constraint.  This will ensure that the alternative will be
152 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
153 ;; architecture extensions.  If all the alternatives in a pattern use the
154 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
155 ;; or TARGET_SIMD.
157 ;; Attribute that specifies whether or not the instruction touches fp
158 ;; registers.  When this is set to yes for an alternative, that alternative
159 ;; will be disabled when !TARGET_FLOAT.
160 (define_attr "fp" "no,yes" (const_string "no"))
162 ;; Attribute that specifies whether or not the instruction touches simd
163 ;; registers.  When this is set to yes for an alternative, that alternative
164 ;; will be disabled when !TARGET_SIMD.
165 (define_attr "simd" "no,yes" (const_string "no"))
167 (define_attr "length" ""
168   (const_int 4))
170 ;; Attribute that controls whether an alternative is enabled or not.
171 ;; Currently it is only used to disable alternatives which touch fp or simd
172 ;; registers when -mgeneral-regs-only is specified.
173 (define_attr "enabled" "no,yes"
174   (cond [(ior
175         (and (eq_attr "fp" "yes")
176              (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
177         (and (eq_attr "simd" "yes")
178              (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
179              (const_string "no")
180         ] (const_string "yes")))
182 ;; -------------------------------------------------------------------
183 ;; Pipeline descriptions and scheduling
184 ;; -------------------------------------------------------------------
186 ;; Processor types.
187 (include "aarch64-tune.md")
189 ;; Scheduling
190 (include "../arm/cortex-a53.md")
191 (include "../arm/cortex-a57.md")
192 (include "thunderx.md")
193 (include "../arm/xgene1.md")
195 ;; -------------------------------------------------------------------
196 ;; Jumps and other miscellaneous insns
197 ;; -------------------------------------------------------------------
199 (define_insn "indirect_jump"
200   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
201   ""
202   "br\\t%0"
203   [(set_attr "type" "branch")]
206 (define_insn "jump"
207   [(set (pc) (label_ref (match_operand 0 "" "")))]
208   ""
209   "b\\t%l0"
210   [(set_attr "type" "branch")]
213 (define_expand "cbranch<mode>4"
214   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
215                             [(match_operand:GPI 1 "register_operand" "")
216                              (match_operand:GPI 2 "aarch64_plus_operand" "")])
217                            (label_ref (match_operand 3 "" ""))
218                            (pc)))]
219   ""
220   "
221   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
222                                          operands[2]);
223   operands[2] = const0_rtx;
224   "
227 (define_expand "cbranch<mode>4"
228   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
229                             [(match_operand:GPF 1 "register_operand" "")
230                              (match_operand:GPF 2 "aarch64_reg_or_zero" "")])
231                            (label_ref (match_operand 3 "" ""))
232                            (pc)))]
233   ""
234   "
235   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
236                                          operands[2]);
237   operands[2] = const0_rtx;
238   "
241 (define_expand "cbranchcc4"
242   [(set (pc) (if_then_else
243               (match_operator 0 "aarch64_comparison_operator"
244                [(match_operand 1 "cc_register" "")
245                 (match_operand 2 "const0_operand")])
246               (label_ref (match_operand 3 "" ""))
247               (pc)))]
248   ""
249   "")
251 (define_insn "ccmp_and<mode>"
252   [(set (match_operand 1 "ccmp_cc_register" "")
253         (compare
254          (and:SI
255           (match_operator 4 "aarch64_comparison_operator"
256            [(match_operand 0 "ccmp_cc_register" "")
257             (const_int 0)])
258           (match_operator 5 "aarch64_comparison_operator"
259            [(match_operand:GPI 2 "register_operand" "r,r,r")
260             (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")]))
261          (const_int 0)))]
262   "aarch64_ccmp_mode_to_code (GET_MODE (operands[1])) == GET_CODE (operands[5])"
263   "@
264    ccmp\\t%<w>2, %<w>3, %k5, %m4
265    ccmp\\t%<w>2, %<w>3, %k5, %m4
266    ccmn\\t%<w>2, #%n3, %k5, %m4"
267   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
270 (define_insn "ccmp_ior<mode>"
271   [(set (match_operand 1 "ccmp_cc_register" "")
272         (compare
273          (ior:SI
274           (match_operator 4 "aarch64_comparison_operator"
275            [(match_operand 0 "ccmp_cc_register" "")
276             (const_int 0)])
277           (match_operator 5 "aarch64_comparison_operator"
278            [(match_operand:GPI 2 "register_operand" "r,r,r")
279             (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")]))
280          (const_int 0)))]
281   "aarch64_ccmp_mode_to_code (GET_MODE (operands[1])) == GET_CODE (operands[5])"
282   "@
283    ccmp\\t%<w>2, %<w>3, %K5, %M4
284    ccmp\\t%<w>2, %<w>3, %K5, %M4
285    ccmn\\t%<w>2, #%n3, %K5, %M4"
286   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
289 (define_expand "cmp<mode>"
290   [(set (match_operand 0 "cc_register" "")
291         (match_operator:CC 1 "aarch64_comparison_operator"
292          [(match_operand:GPI 2 "register_operand" "")
293           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
294   ""
295   {
296     operands[1] = gen_rtx_fmt_ee (COMPARE,
297                                   SELECT_CC_MODE (GET_CODE (operands[1]),
298                                                   operands[2], operands[3]),
299                                   operands[2], operands[3]);
300   }
303 (define_insn "*condjump"
304   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
305                             [(match_operand 1 "cc_register" "") (const_int 0)])
306                            (label_ref (match_operand 2 "" ""))
307                            (pc)))]
308   ""
309   "b%m0\\t%l2"
310   [(set_attr "type" "branch")]
313 (define_expand "casesi"
314   [(match_operand:SI 0 "register_operand" "")   ; Index
315    (match_operand:SI 1 "const_int_operand" "")  ; Lower bound
316    (match_operand:SI 2 "const_int_operand" "")  ; Total range
317    (match_operand:DI 3 "" "")                   ; Table label
318    (match_operand:DI 4 "" "")]                  ; Out of range label
319   ""
320   {
321     if (operands[1] != const0_rtx)
322       {
323         rtx reg = gen_reg_rtx (SImode);
325         /* Canonical RTL says that if you have:
327            (minus (X) (CONST))
329            then this should be emitted as:
331            (plus (X) (-CONST))
333            The use of trunc_int_for_mode ensures that the resulting
334            constant can be represented in SImode, this is important
335            for the corner case where operand[1] is INT_MIN.  */
337         operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
339         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
340               (operands[1], SImode))
341           operands[1] = force_reg (SImode, operands[1]);
342         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
343         operands[0] = reg;
344       }
346     if (!aarch64_plus_operand (operands[2], SImode))
347       operands[2] = force_reg (SImode, operands[2]);
348     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
349                                                  const0_rtx),
350                                     operands[0], operands[2], operands[4]));
352     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
353     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
354                                          operands[3]));
355     DONE;
356   }
359 (define_insn "casesi_dispatch"
360   [(parallel
361     [(set (pc)
362           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
363                            (match_operand:SI 1 "register_operand" "r")]
364                         UNSPEC_CASESI)))
365      (clobber (reg:CC CC_REGNUM))
366      (clobber (match_scratch:DI 3 "=r"))
367      (clobber (match_scratch:DI 4 "=r"))
368      (use (label_ref (match_operand 2 "" "")))])]
369   ""
370   "*
371   return aarch64_output_casesi (operands);
372   "
373   [(set_attr "length" "16")
374    (set_attr "type" "branch")]
377 (define_insn "nop"
378   [(unspec[(const_int 0)] UNSPEC_NOP)]
379   ""
380   "nop"
381   [(set_attr "type" "no_insn")]
384 (define_insn "prefetch"
385   [(prefetch (match_operand:DI 0 "address_operand" "r")
386             (match_operand:QI 1 "const_int_operand" "")
387             (match_operand:QI 2 "const_int_operand" ""))]
388   ""
389   {
390     const char * pftype[2][4] = 
391     {
392       {"prfm\\tPLDL1STRM, %a0",
393        "prfm\\tPLDL3KEEP, %a0",
394        "prfm\\tPLDL2KEEP, %a0",
395        "prfm\\tPLDL1KEEP, %a0"},
396       {"prfm\\tPSTL1STRM, %a0",
397        "prfm\\tPSTL3KEEP, %a0",
398        "prfm\\tPSTL2KEEP, %a0",
399        "prfm\\tPSTL1KEEP, %a0"},
400     };
402     int locality = INTVAL (operands[2]);
404     gcc_assert (IN_RANGE (locality, 0, 3));
406     return pftype[INTVAL(operands[1])][locality];
407   }
408   [(set_attr "type" "load1")]
411 (define_insn "trap"
412   [(trap_if (const_int 1) (const_int 8))]
413   ""
414   "brk #1000"
415   [(set_attr "type" "trap")])
417 (define_expand "prologue"
418   [(clobber (const_int 0))]
419   ""
420   "
421   aarch64_expand_prologue ();
422   DONE;
423   "
426 (define_expand "epilogue"
427   [(clobber (const_int 0))]
428   ""
429   "
430   aarch64_expand_epilogue (false);
431   DONE;
432   "
435 (define_expand "sibcall_epilogue"
436   [(clobber (const_int 0))]
437   ""
438   "
439   aarch64_expand_epilogue (true);
440   DONE;
441   "
444 (define_insn "*do_return"
445   [(return)]
446   ""
447   "ret"
448   [(set_attr "type" "branch")]
451 (define_expand "return"
452   [(simple_return)]
453   "aarch64_use_return_insn_p ()"
454   ""
457 (define_insn "simple_return"
458   [(simple_return)]
459   ""
460   "ret"
461   [(set_attr "type" "branch")]
464 (define_insn "eh_return"
465   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
466     UNSPECV_EH_RETURN)]
467   ""
468   "#"
469   [(set_attr "type" "branch")]
473 (define_split
474   [(unspec_volatile [(match_operand:DI 0 "register_operand" "")]
475     UNSPECV_EH_RETURN)]
476   "reload_completed"
477   [(set (match_dup 1) (match_dup 0))]
478   {
479     operands[1] = aarch64_final_eh_return_addr ();
480   }
483 (define_insn "*cb<optab><mode>1"
484   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
485                                 (const_int 0))
486                            (label_ref (match_operand 1 "" ""))
487                            (pc)))]
488   ""
489   "<cbz>\\t%<w>0, %l1"
490   [(set_attr "type" "branch")]
494 (define_insn "*tb<optab><mode>1"
495   [(set (pc) (if_then_else
496               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
497                                     (const_int 1)
498                                     (match_operand 1 "const_int_operand" "n"))
499                    (const_int 0))
500              (label_ref (match_operand 2 "" ""))
501              (pc)))
502    (clobber (reg:CC CC_REGNUM))]
503   ""
504   {
505     if (get_attr_length (insn) == 8)
506       {
507         operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
508         return "tst\t%<w>0, %1\;<bcond>\t%l2";
509       }
510     else
511       return "<tbz>\t%<w>0, %1, %l2";
512   }
513   [(set_attr "type" "branch")
514    (set (attr "length")
515         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
516                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
517                       (const_int 4)
518                       (const_int 8)))]
521 (define_insn "*cb<optab><mode>1"
522   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
523                                  (const_int 0))
524                            (label_ref (match_operand 1 "" ""))
525                            (pc)))
526    (clobber (reg:CC CC_REGNUM))]
527   ""
528   {
529     if (get_attr_length (insn) == 8)
530       {
531         char buf[64];
532         uint64_t val = ((uint64_t ) 1)
533                         << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
534         sprintf (buf, "tst\t%%<w>0, %"PRId64, val);
535         output_asm_insn (buf, operands);
536         return "<bcond>\t%l1";
537       }
538     else
539       return "<tbz>\t%<w>0, <sizem1>, %l1";
540   }
541   [(set_attr "type" "branch")
542    (set (attr "length")
543         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
544                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
545                       (const_int 4)
546                       (const_int 8)))]
549 ;; -------------------------------------------------------------------
550 ;; Subroutine calls and sibcalls
551 ;; -------------------------------------------------------------------
553 (define_expand "call_internal"
554   [(parallel [(call (match_operand 0 "memory_operand" "")
555                     (match_operand 1 "general_operand" ""))
556               (use (match_operand 2 "" ""))
557               (clobber (reg:DI LR_REGNUM))])])
559 (define_expand "call"
560   [(parallel [(call (match_operand 0 "memory_operand" "")
561                     (match_operand 1 "general_operand" ""))
562               (use (match_operand 2 "" ""))
563               (clobber (reg:DI LR_REGNUM))])]
564   ""
565   "
566   {
567     rtx callee, pat;
569     /* In an untyped call, we can get NULL for operand 2.  */
570     if (operands[2] == NULL)
571       operands[2] = const0_rtx;
573     /* Decide if we should generate indirect calls by loading the
574        64-bit address of the callee into a register before performing
575        the branch-and-link.  */
576     callee = XEXP (operands[0], 0);
577     if (GET_CODE (callee) == SYMBOL_REF
578         ? aarch64_is_long_call_p (callee)
579         : !REG_P (callee))
580       XEXP (operands[0], 0) = force_reg (Pmode, callee);
582     pat = gen_call_internal (operands[0], operands[1], operands[2]);
583     aarch64_emit_call_insn (pat);
584     DONE;
585   }"
588 (define_insn "*call_reg"
589   [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
590          (match_operand 1 "" ""))
591    (use (match_operand 2 "" ""))
592    (clobber (reg:DI LR_REGNUM))]
593   ""
594   "blr\\t%0"
595   [(set_attr "type" "call")]
598 (define_insn "*call_symbol"
599   [(call (mem:DI (match_operand:DI 0 "" ""))
600          (match_operand 1 "" ""))
601    (use (match_operand 2 "" ""))
602    (clobber (reg:DI LR_REGNUM))]
603   "GET_CODE (operands[0]) == SYMBOL_REF
604    && !aarch64_is_long_call_p (operands[0])"
605   "bl\\t%a0"
606   [(set_attr "type" "call")]
609 (define_expand "call_value_internal"
610   [(parallel [(set (match_operand 0 "" "")
611                    (call (match_operand 1 "memory_operand" "")
612                          (match_operand 2 "general_operand" "")))
613               (use (match_operand 3 "" ""))
614               (clobber (reg:DI LR_REGNUM))])])
616 (define_expand "call_value"
617   [(parallel [(set (match_operand 0 "" "")
618                    (call (match_operand 1 "memory_operand" "")
619                          (match_operand 2 "general_operand" "")))
620               (use (match_operand 3 "" ""))
621               (clobber (reg:DI LR_REGNUM))])]
622   ""
623   "
624   {
625     rtx callee, pat;
627     /* In an untyped call, we can get NULL for operand 3.  */
628     if (operands[3] == NULL)
629       operands[3] = const0_rtx;
631     /* Decide if we should generate indirect calls by loading the
632        64-bit address of the callee into a register before performing
633        the branch-and-link.  */
634     callee = XEXP (operands[1], 0);
635     if (GET_CODE (callee) == SYMBOL_REF
636         ? aarch64_is_long_call_p (callee)
637         : !REG_P (callee))
638       XEXP (operands[1], 0) = force_reg (Pmode, callee);
640     pat = gen_call_value_internal (operands[0], operands[1], operands[2],
641                                    operands[3]);
642     aarch64_emit_call_insn (pat);
643     DONE;
644   }"
647 (define_insn "*call_value_reg"
648   [(set (match_operand 0 "" "")
649         (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
650                       (match_operand 2 "" "")))
651    (use (match_operand 3 "" ""))
652    (clobber (reg:DI LR_REGNUM))]
653   ""
654   "blr\\t%1"
655   [(set_attr "type" "call")]
659 (define_insn "*call_value_symbol"
660   [(set (match_operand 0 "" "")
661         (call (mem:DI (match_operand:DI 1 "" ""))
662               (match_operand 2 "" "")))
663    (use (match_operand 3 "" ""))
664    (clobber (reg:DI LR_REGNUM))]
665   "GET_CODE (operands[1]) == SYMBOL_REF
666    && !aarch64_is_long_call_p (operands[1])"
667   "bl\\t%a1"
668   [(set_attr "type" "call")]
671 (define_expand "sibcall_internal"
672   [(parallel [(call (match_operand 0 "memory_operand" "")
673                     (match_operand 1 "general_operand" ""))
674               (return)
675               (use (match_operand 2 "" ""))])])
677 (define_expand "sibcall"
678   [(parallel [(call (match_operand 0 "memory_operand" "")
679                     (match_operand 1 "general_operand" ""))
680               (return)
681               (use (match_operand 2 "" ""))])]
682   ""
683   {
684     rtx pat;
686     if (!REG_P (XEXP (operands[0], 0))
687        && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF))
688      XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
690     if (operands[2] == NULL_RTX)
691       operands[2] = const0_rtx;
693     pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
694     aarch64_emit_call_insn (pat);
695     DONE;
696   }
699 (define_expand "sibcall_value_internal"
700   [(parallel [(set (match_operand 0 "" "")
701                    (call (match_operand 1 "memory_operand" "")
702                          (match_operand 2 "general_operand" "")))
703               (return)
704               (use (match_operand 3 "" ""))])])
706 (define_expand "sibcall_value"
707   [(parallel [(set (match_operand 0 "" "")
708                    (call (match_operand 1 "memory_operand" "")
709                          (match_operand 2 "general_operand" "")))
710               (return)
711               (use (match_operand 3 "" ""))])]
712   ""
713   {
714     rtx pat;
716     if (!REG_P (XEXP (operands[1], 0))
717        && (GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF))
718      XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
720     if (operands[3] == NULL_RTX)
721       operands[3] = const0_rtx;
723     pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2],
724                                       operands[3]);
725     aarch64_emit_call_insn (pat);
726     DONE;
727   }
730 (define_insn "*sibcall_insn"
731   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
732          (match_operand 1 "" ""))
733    (return)
734    (use (match_operand 2 "" ""))]
735   "SIBLING_CALL_P (insn)"
736   "@
737    br\\t%0
738    b\\t%a0"
739   [(set_attr "type" "branch, branch")]
742 (define_insn "*sibcall_value_insn"
743   [(set (match_operand 0 "" "")
744         (call (mem:DI
745                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
746               (match_operand 2 "" "")))
747    (return)
748    (use (match_operand 3 "" ""))]
749   "SIBLING_CALL_P (insn)"
750   "@
751    br\\t%1
752    b\\t%a1"
753   [(set_attr "type" "branch, branch")]
756 ;; Call subroutine returning any type.
758 (define_expand "untyped_call"
759   [(parallel [(call (match_operand 0 "")
760                     (const_int 0))
761               (match_operand 1 "")
762               (match_operand 2 "")])]
763   ""
765   int i;
767   emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
769   for (i = 0; i < XVECLEN (operands[2], 0); i++)
770     {
771       rtx set = XVECEXP (operands[2], 0, i);
772       emit_move_insn (SET_DEST (set), SET_SRC (set));
773     }
775   /* The optimizer does not know that the call sets the function value
776      registers we stored in the result block.  We avoid problems by
777      claiming that all hard registers are used and clobbered at this
778      point.  */
779   emit_insn (gen_blockage ());
780   DONE;
783 ;; -------------------------------------------------------------------
784 ;; Moves
785 ;; -------------------------------------------------------------------
787 (define_expand "mov<mode>"
788   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
789         (match_operand:SHORT 1 "general_operand" ""))]
790   ""
791   "
792     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
793       operands[1] = force_reg (<MODE>mode, operands[1]);
794   "
797 (define_insn "*mov<mode>_aarch64"
798   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,   *w,r,*w, m, m, r,*w,*w")
799         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m, m,rZ,*w,*w, r,*w"))]
800   "(register_operand (operands[0], <MODE>mode)
801     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
803    switch (which_alternative)
804      {
805      case 0:
806        return "mov\t%w0, %w1";
807      case 1:
808        return "mov\t%w0, %1";
809      case 2:
810        return aarch64_output_scalar_simd_mov_immediate (operands[1],
811                                                         <MODE>mode);
812      case 3:
813        return "ldr<size>\t%w0, %1";
814      case 4:
815        return "ldr\t%<size>0, %1";
816      case 5:
817        return "str<size>\t%w1, %0";
818      case 6:
819        return "str\t%<size>1, %0";
820      case 7:
821        return "umov\t%w0, %1.<v>[0]";
822      case 8:
823        return "dup\t%0.<Vallxd>, %w1";
824      case 9:
825        return "dup\t%<Vetype>0, %1.<v>[0]";
826      default:
827        gcc_unreachable ();
828      }
830   [(set_attr "type" "mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
831                      neon_to_gp<q>,neon_from_gp<q>,neon_dup")
832    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")]
835 (define_expand "mov<mode>"
836   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
837         (match_operand:GPI 1 "general_operand" ""))]
838   ""
839   "
840     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
841       operands[1] = force_reg (<MODE>mode, operands[1]);
843     /* FIXME: RR we still need to fix up what we are doing with
844        symbol_refs and other types of constants.  */
845     if (CONSTANT_P (operands[1])
846         && !CONST_INT_P (operands[1]))
847      {
848        aarch64_expand_mov_immediate (operands[0], operands[1]);
849        DONE;
850      }
851   "
854 (define_insn_and_split "*movsi_aarch64"
855   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r  ,*w, r,*w")
856         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,m, m,rZ,*w,S,Ush,rZ,*w,*w"))]
857   "(register_operand (operands[0], SImode)
858     || aarch64_reg_or_zero (operands[1], SImode))"
859   "@
860    mov\\t%w0, %w1
861    mov\\t%w0, %w1
862    mov\\t%w0, %w1
863    mov\\t%w0, %1
864    #
865    ldr\\t%w0, %1
866    ldr\\t%s0, %1
867    str\\t%w1, %0
868    str\\t%s1, %0
869    adr\\t%x0, %a1
870    adrp\\t%x0, %A1
871    fmov\\t%s0, %w1
872    fmov\\t%w0, %s1
873    fmov\\t%s0, %s1"
874    "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
875     && GP_REGNUM_P (REGNO (operands[0]))"
876    [(const_int 0)]
877    "{
878        aarch64_expand_mov_immediate (operands[0], operands[1]);
879        DONE;
880     }"
881   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
882                      adr,adr,f_mcr,f_mrc,fmov")
883    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
886 (define_insn_and_split "*movdi_aarch64"
887   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m,  m,r,r,  *w, r,*w,w")
888         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,n,m, m,rZ,*w,S,Ush,rZ,*w,*w,Dd"))]
889   "(register_operand (operands[0], DImode)
890     || aarch64_reg_or_zero (operands[1], DImode))"
891   "@
892    mov\\t%x0, %x1
893    mov\\t%0, %x1
894    mov\\t%x0, %1
895    mov\\t%x0, %1
896    #
897    ldr\\t%x0, %1
898    ldr\\t%d0, %1
899    str\\t%x1, %0
900    str\\t%d1, %0
901    adr\\t%x0, %a1
902    adrp\\t%x0, %A1
903    fmov\\t%d0, %x1
904    fmov\\t%x0, %d1
905    fmov\\t%d0, %d1
906    movi\\t%d0, %1"
907    "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
908     && GP_REGNUM_P (REGNO (operands[0]))"
909    [(const_int 0)]
910    "{
911        aarch64_expand_mov_immediate (operands[0], operands[1]);
912        DONE;
913     }"
914   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
915                      adr,adr,f_mcr,f_mrc,fmov,fmov")
916    (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
917    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
920 (define_insn "insv_imm<mode>"
921   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
922                           (const_int 16)
923                           (match_operand:GPI 1 "const_int_operand" "n"))
924         (match_operand:GPI 2 "const_int_operand" "n"))]
925   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
926    && UINTVAL (operands[1]) % 16 == 0"
927   "movk\\t%<w>0, %X2, lsl %1"
928   [(set_attr "type" "mov_imm")]
931 (define_expand "movti"
932   [(set (match_operand:TI 0 "nonimmediate_operand" "")
933         (match_operand:TI 1 "general_operand" ""))]
934   ""
935   "
936     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
937       operands[1] = force_reg (TImode, operands[1]);
938   "
941 (define_insn "*movti_aarch64"
942   [(set (match_operand:TI 0
943          "nonimmediate_operand"  "=r, *w,r ,*w,r  ,Ump,Ump,*w,m")
944         (match_operand:TI 1
945          "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r  ,Z  , m,*w"))]
946   "(register_operand (operands[0], TImode)
947     || aarch64_reg_or_zero (operands[1], TImode))"
948   "@
949    #
950    #
951    #
952    orr\\t%0.16b, %1.16b, %1.16b
953    ldp\\t%0, %H0, %1
954    stp\\t%1, %H1, %0
955    stp\\txzr, xzr, %0
956    ldr\\t%q0, %1
957    str\\t%q1, %0"
958   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
959                              load2,store2,store2,f_loadd,f_stored")
960    (set_attr "length" "8,8,8,4,4,4,4,4,4")
961    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
962    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
965 ;; Split a TImode register-register or register-immediate move into
966 ;; its component DImode pieces, taking care to handle overlapping
967 ;; source and dest registers.
968 (define_split
969    [(set (match_operand:TI 0 "register_operand" "")
970          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
971   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
972   [(const_int 0)]
974   aarch64_split_128bit_move (operands[0], operands[1]);
975   DONE;
978 (define_expand "mov<mode>"
979   [(set (match_operand:GPF 0 "nonimmediate_operand" "")
980         (match_operand:GPF 1 "general_operand" ""))]
981   ""
982   "
983     if (!TARGET_FLOAT)
984      {
985         sorry (\"%qs and floating point code\", \"-mgeneral-regs-only\");
986         FAIL;
987      }
989     if (GET_CODE (operands[0]) == MEM)
990       operands[1] = force_reg (<MODE>mode, operands[1]);
991   "
994 (define_insn "*movsf_aarch64"
995   [(set (match_operand:SF 0 "nonimmediate_operand" "=w, ?r,w,w  ,w,m,r,m ,r")
996         (match_operand:SF 1 "general_operand"      "?rY, w,w,Ufc,m,w,m,rY,r"))]
997   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
998     || register_operand (operands[1], SFmode))"
999   "@
1000    fmov\\t%s0, %w1
1001    fmov\\t%w0, %s1
1002    fmov\\t%s0, %s1
1003    fmov\\t%s0, %1
1004    ldr\\t%s0, %1
1005    str\\t%s1, %0
1006    ldr\\t%w0, %1
1007    str\\t%w1, %0
1008    mov\\t%w0, %w1"
1009   [(set_attr "type" "f_mcr,f_mrc,fmov,fconsts,\
1010                      f_loads,f_stores,f_loads,f_stores,mov_reg")]
1013 (define_insn "*movdf_aarch64"
1014   [(set (match_operand:DF 0 "nonimmediate_operand" "=w, ?r,w,w  ,w,m,r,m ,r")
1015         (match_operand:DF 1 "general_operand"      "?rY, w,w,Ufc,m,w,m,rY,r"))]
1016   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1017     || register_operand (operands[1], DFmode))"
1018   "@
1019    fmov\\t%d0, %x1
1020    fmov\\t%x0, %d1
1021    fmov\\t%d0, %d1
1022    fmov\\t%d0, %1
1023    ldr\\t%d0, %1
1024    str\\t%d1, %0
1025    ldr\\t%x0, %1
1026    str\\t%x1, %0
1027    mov\\t%x0, %x1"
1028   [(set_attr "type" "f_mcr,f_mrc,fmov,fconstd,\
1029                      f_loadd,f_stored,f_loadd,f_stored,mov_reg")]
1032 (define_expand "movtf"
1033   [(set (match_operand:TF 0 "nonimmediate_operand" "")
1034         (match_operand:TF 1 "general_operand" ""))]
1035   ""
1036   "
1037     if (!TARGET_FLOAT)
1038      {
1039         sorry (\"%qs and floating point code\", \"-mgeneral-regs-only\");
1040         FAIL;
1041      }
1043     if (GET_CODE (operands[0]) == MEM)
1044       operands[1] = force_reg (TFmode, operands[1]);
1045   "
1048 (define_insn "*movtf_aarch64"
1049   [(set (match_operand:TF 0
1050          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump")
1051         (match_operand:TF 1
1052          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,Ump,?rY"))]
1053   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1054     || register_operand (operands[1], TFmode))"
1055   "@
1056    orr\\t%0.16b, %1.16b, %1.16b
1057    #
1058    #
1059    #
1060    movi\\t%0.2d, #0
1061    fmov\\t%s0, wzr
1062    ldr\\t%q0, %1
1063    str\\t%q1, %0
1064    ldp\\t%0, %H0, %1
1065    stp\\t%1, %H1, %0"
1066   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,fconstd,fconstd,\
1067                      f_loadd,f_stored,neon_load1_2reg,neon_store1_2reg")
1068    (set_attr "length" "4,8,8,8,4,4,4,4,4,4")
1069    (set_attr "fp" "*,*,yes,yes,*,yes,yes,yes,*,*")
1070    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*")]
1073 (define_split
1074    [(set (match_operand:TF 0 "register_operand" "")
1075          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1076   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1077   [(const_int 0)]
1078   {
1079     aarch64_split_128bit_move (operands[0], operands[1]);
1080     DONE;
1081   }
1084 ;; 0 is dst
1085 ;; 1 is src
1086 ;; 2 is size of move in bytes
1087 ;; 3 is alignment
1089 (define_expand "movmemdi"
1090   [(match_operand:BLK 0 "memory_operand")
1091    (match_operand:BLK 1 "memory_operand")
1092    (match_operand:DI 2 "immediate_operand")
1093    (match_operand:DI 3 "immediate_operand")]
1094    "!STRICT_ALIGNMENT"
1096   if (aarch64_expand_movmem (operands))
1097     DONE;
1098   FAIL;
1102 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1103 ;; fairly lax checking on the second memory operation.
1104 (define_insn "load_pairsi"
1105   [(set (match_operand:SI 0 "register_operand" "=r,*w")
1106         (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1107    (set (match_operand:SI 2 "register_operand" "=r,*w")
1108         (match_operand:SI 3 "memory_operand" "m,m"))]
1109   "rtx_equal_p (XEXP (operands[3], 0),
1110                 plus_constant (Pmode,
1111                                XEXP (operands[1], 0),
1112                                GET_MODE_SIZE (SImode)))"
1113   "@
1114    ldp\\t%w0, %w2, %1
1115    ldp\\t%s0, %s2, %1"
1116   [(set_attr "type" "load2,neon_load1_2reg")
1117    (set_attr "fp" "*,yes")]
1120 (define_insn "load_pairdi"
1121   [(set (match_operand:DI 0 "register_operand" "=r,*w")
1122         (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1123    (set (match_operand:DI 2 "register_operand" "=r,*w")
1124         (match_operand:DI 3 "memory_operand" "m,m"))]
1125   "rtx_equal_p (XEXP (operands[3], 0),
1126                 plus_constant (Pmode,
1127                                XEXP (operands[1], 0),
1128                                GET_MODE_SIZE (DImode)))"
1129   "@
1130    ldp\\t%x0, %x2, %1
1131    ldp\\t%d0, %d2, %1"
1132   [(set_attr "type" "load2,neon_load1_2reg")
1133    (set_attr "fp" "*,yes")]
1137 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1138 ;; fairly lax checking on the second memory operation.
1139 (define_insn "store_pairsi"
1140   [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1141         (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w"))
1142    (set (match_operand:SI 2 "memory_operand" "=m,m")
1143         (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1144   "rtx_equal_p (XEXP (operands[2], 0),
1145                 plus_constant (Pmode,
1146                                XEXP (operands[0], 0),
1147                                GET_MODE_SIZE (SImode)))"
1148   "@
1149    stp\\t%w1, %w3, %0
1150    stp\\t%s1, %s3, %0"
1151   [(set_attr "type" "store2,neon_store1_2reg")
1152    (set_attr "fp" "*,yes")]
1155 (define_insn "store_pairdi"
1156   [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1157         (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w"))
1158    (set (match_operand:DI 2 "memory_operand" "=m,m")
1159         (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))]
1160   "rtx_equal_p (XEXP (operands[2], 0),
1161                 plus_constant (Pmode,
1162                                XEXP (operands[0], 0),
1163                                GET_MODE_SIZE (DImode)))"
1164   "@
1165    stp\\t%x1, %x3, %0
1166    stp\\t%d1, %d3, %0"
1167   [(set_attr "type" "store2,neon_store1_2reg")
1168    (set_attr "fp" "*,yes")]
1171 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1172 ;; fairly lax checking on the second memory operation.
1173 (define_insn "load_pairsf"
1174   [(set (match_operand:SF 0 "register_operand" "=w,*r")
1175         (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1176    (set (match_operand:SF 2 "register_operand" "=w,*r")
1177         (match_operand:SF 3 "memory_operand" "m,m"))]
1178   "rtx_equal_p (XEXP (operands[3], 0),
1179                 plus_constant (Pmode,
1180                                XEXP (operands[1], 0),
1181                                GET_MODE_SIZE (SFmode)))"
1182   "@
1183    ldp\\t%s0, %s2, %1
1184    ldp\\t%w0, %w2, %1"
1185   [(set_attr "type" "neon_load1_2reg,load2")
1186    (set_attr "fp" "yes,*")]
1189 (define_insn "load_pairdf"
1190   [(set (match_operand:DF 0 "register_operand" "=w,*r")
1191         (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1192    (set (match_operand:DF 2 "register_operand" "=w,*r")
1193         (match_operand:DF 3 "memory_operand" "m,m"))]
1194   "rtx_equal_p (XEXP (operands[3], 0),
1195                 plus_constant (Pmode,
1196                                XEXP (operands[1], 0),
1197                                GET_MODE_SIZE (DFmode)))"
1198   "@
1199    ldp\\t%d0, %d2, %1
1200    ldp\\t%x0, %x2, %1"
1201   [(set_attr "type" "neon_load1_2reg,load2")
1202    (set_attr "fp" "yes,*")]
1205 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1206 ;; fairly lax checking on the second memory operation.
1207 (define_insn "store_pairsf"
1208   [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1209         (match_operand:SF 1 "register_operand" "w,*r"))
1210    (set (match_operand:SF 2 "memory_operand" "=m,m")
1211         (match_operand:SF 3 "register_operand" "w,*r"))]
1212   "rtx_equal_p (XEXP (operands[2], 0),
1213                 plus_constant (Pmode,
1214                                XEXP (operands[0], 0),
1215                                GET_MODE_SIZE (SFmode)))"
1216   "@
1217    stp\\t%s1, %s3, %0
1218    stp\\t%w1, %w3, %0"
1219   [(set_attr "type" "neon_store1_2reg,store2")
1220    (set_attr "fp" "yes,*")]
1223 (define_insn "store_pairdf"
1224   [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1225         (match_operand:DF 1 "register_operand" "w,*r"))
1226    (set (match_operand:DF 2 "memory_operand" "=m,m")
1227         (match_operand:DF 3 "register_operand" "w,*r"))]
1228   "rtx_equal_p (XEXP (operands[2], 0),
1229                 plus_constant (Pmode,
1230                                XEXP (operands[0], 0),
1231                                GET_MODE_SIZE (DFmode)))"
1232   "@
1233    stp\\t%d1, %d3, %0
1234    stp\\t%x1, %x3, %0"
1235   [(set_attr "type" "neon_store1_2reg,store2")
1236    (set_attr "fp" "yes,*")]
1239 ;; Load pair with post-index writeback.  This is primarily used in function
1240 ;; epilogues.
1241 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1242   [(parallel
1243     [(set (match_operand:P 0 "register_operand" "=k")
1244           (plus:P (match_operand:P 1 "register_operand" "0")
1245                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1246      (set (match_operand:GPI 2 "register_operand" "=r")
1247           (mem:GPI (match_dup 1)))
1248      (set (match_operand:GPI 3 "register_operand" "=r")
1249           (mem:GPI (plus:P (match_dup 1)
1250                    (match_operand:P 5 "const_int_operand" "n"))))])]
1251   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1252   "ldp\\t%<w>2, %<w>3, [%1], %4"
1253   [(set_attr "type" "load2")]
1256 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1257   [(parallel
1258     [(set (match_operand:P 0 "register_operand" "=k")
1259           (plus:P (match_operand:P 1 "register_operand" "0")
1260                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1261      (set (match_operand:GPF 2 "register_operand" "=w")
1262           (mem:GPF (match_dup 1)))
1263      (set (match_operand:GPF 3 "register_operand" "=w")
1264           (mem:GPF (plus:P (match_dup 1)
1265                    (match_operand:P 5 "const_int_operand" "n"))))])]
1266   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1267   "ldp\\t%<w>2, %<w>3, [%1], %4"
1268   [(set_attr "type" "neon_load1_2reg")]
1271 ;; Store pair with pre-index writeback.  This is primarily used in function
1272 ;; prologues.
1273 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1274   [(parallel
1275     [(set (match_operand:P 0 "register_operand" "=&k")
1276           (plus:P (match_operand:P 1 "register_operand" "0")
1277                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1278      (set (mem:GPI (plus:P (match_dup 0)
1279                    (match_dup 4)))
1280           (match_operand:GPI 2 "register_operand" "r"))
1281      (set (mem:GPI (plus:P (match_dup 0)
1282                    (match_operand:P 5 "const_int_operand" "n")))
1283           (match_operand:GPI 3 "register_operand" "r"))])]
1284   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1285   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1286   [(set_attr "type" "store2")]
1289 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1290   [(parallel
1291     [(set (match_operand:P 0 "register_operand" "=&k")
1292           (plus:P (match_operand:P 1 "register_operand" "0")
1293                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1294      (set (mem:GPF (plus:P (match_dup 0)
1295                    (match_dup 4)))
1296           (match_operand:GPF 2 "register_operand" "w"))
1297      (set (mem:GPF (plus:P (match_dup 0)
1298                    (match_operand:P 5 "const_int_operand" "n")))
1299           (match_operand:GPF 3 "register_operand" "w"))])]
1300   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1301   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1302   [(set_attr "type" "neon_store1_2reg<q>")]
1305 ;; -------------------------------------------------------------------
1306 ;; Sign/Zero extension
1307 ;; -------------------------------------------------------------------
1309 (define_expand "<optab>sidi2"
1310   [(set (match_operand:DI 0 "register_operand")
1311         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1312   ""
1315 (define_insn "*extendsidi2_aarch64"
1316   [(set (match_operand:DI 0 "register_operand" "=r,r")
1317         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1318   ""
1319   "@
1320    sxtw\t%0, %w1
1321    ldrsw\t%0, %1"
1322   [(set_attr "type" "extend,load1")]
1325 (define_insn "*load_pair_extendsidi2_aarch64"
1326   [(set (match_operand:DI 0 "register_operand" "=r")
1327         (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1328    (set (match_operand:DI 2 "register_operand" "=r")
1329         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1330   "rtx_equal_p (XEXP (operands[3], 0),
1331                 plus_constant (Pmode,
1332                                XEXP (operands[1], 0),
1333                                GET_MODE_SIZE (SImode)))"
1334   "ldpsw\\t%0, %2, %1"
1335   [(set_attr "type" "load2")]
1338 (define_insn "*zero_extendsidi2_aarch64"
1339   [(set (match_operand:DI 0 "register_operand" "=r,r")
1340         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1341   ""
1342   "@
1343    uxtw\t%0, %w1
1344    ldr\t%w0, %1"
1345   [(set_attr "type" "extend,load1")]
1348 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1349   [(set (match_operand:DI 0 "register_operand" "=r")
1350         (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1351    (set (match_operand:DI 2 "register_operand" "=r")
1352         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1353   "rtx_equal_p (XEXP (operands[3], 0),
1354                 plus_constant (Pmode,
1355                                XEXP (operands[1], 0),
1356                                GET_MODE_SIZE (SImode)))"
1357   "ldp\\t%w0, %w2, %1"
1358   [(set_attr "type" "load2")]
1361 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1362   [(set (match_operand:GPI 0 "register_operand")
1363         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1364   ""
1367 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1368   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1369         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1370   ""
1371   "@
1372    sxt<SHORT:size>\t%<GPI:w>0, %w1
1373    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1374   [(set_attr "type" "extend,load1")]
1377 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1378   [(set (match_operand:GPI 0 "register_operand" "=r,r,*w")
1379         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1380   ""
1381   "@
1382    uxt<SHORT:size>\t%<GPI:w>0, %w1
1383    ldr<SHORT:size>\t%w0, %1
1384    ldr\t%<SHORT:size>0, %1"
1385   [(set_attr "type" "extend,load1,load1")]
1388 (define_expand "<optab>qihi2"
1389   [(set (match_operand:HI 0 "register_operand")
1390         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1391   ""
1394 (define_insn "*<optab>qihi2_aarch64"
1395   [(set (match_operand:HI 0 "register_operand" "=r,r")
1396         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1397   ""
1398   "@
1399    <su>xtb\t%w0, %w1
1400    <ldrxt>b\t%w0, %1"
1401   [(set_attr "type" "extend,load1")]
1404 ;; -------------------------------------------------------------------
1405 ;; Simple arithmetic
1406 ;; -------------------------------------------------------------------
1408 (define_expand "add<mode>3"
1409   [(set
1410     (match_operand:GPI 0 "register_operand" "")
1411     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1412               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1413   ""
1414   "
1415   if (! aarch64_plus_operand (operands[2], VOIDmode))
1416     {
1417       HOST_WIDE_INT imm = INTVAL (operands[2]);
1419       if (aarch64_move_imm (imm, <MODE>mode) && can_create_pseudo_p ())
1420         {
1421           rtx tmp = gen_reg_rtx (<MODE>mode);
1422           emit_move_insn (tmp, operands[2]);
1423           operands[2] = tmp;
1424         }
1425       else
1426         {
1427           rtx subtarget = ((optimize && can_create_pseudo_p ())
1428                            ? gen_reg_rtx (<MODE>mode) : operands[0]);
1430           if (imm < 0)
1431             imm = -(-imm & ~0xfff);
1432           else
1433             imm &= ~0xfff;
1435           emit_insn (gen_add<mode>3 (subtarget, operands[1], GEN_INT (imm)));
1436           operands[1] = subtarget;
1437           operands[2] = GEN_INT (INTVAL (operands[2]) - imm);
1438         }
1439     }
1440   "
1443 (define_insn "*addsi3_aarch64"
1444   [(set
1445     (match_operand:SI 0 "register_operand" "=rk,rk,w,rk")
1446     (plus:SI
1447      (match_operand:SI 1 "register_operand" "%rk,rk,w,rk")
1448      (match_operand:SI 2 "aarch64_plus_operand" "I,r,w,J")))]
1449   ""
1450   "@
1451   add\\t%w0, %w1, %2
1452   add\\t%w0, %w1, %w2
1453   add\\t%0.2s, %1.2s, %2.2s
1454   sub\\t%w0, %w1, #%n2"
1455   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm")
1456    (set_attr "simd" "*,*,yes,*")]
1459 ;; zero_extend version of above
1460 (define_insn "*addsi3_aarch64_uxtw"
1461   [(set
1462     (match_operand:DI 0 "register_operand" "=rk,rk,rk")
1463     (zero_extend:DI
1464      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk")
1465               (match_operand:SI 2 "aarch64_plus_operand" "I,r,J"))))]
1466   ""
1467   "@
1468   add\\t%w0, %w1, %2
1469   add\\t%w0, %w1, %w2
1470   sub\\t%w0, %w1, #%n2"
1471   [(set_attr "type" "alu_imm,alu_sreg,alu_imm")]
1474 (define_insn "*adddi3_aarch64"
1475   [(set
1476     (match_operand:DI 0 "register_operand" "=rk,rk,rk,w")
1477     (plus:DI
1478      (match_operand:DI 1 "register_operand" "%rk,rk,rk,w")
1479      (match_operand:DI 2 "aarch64_plus_operand" "I,r,J,w")))]
1480   ""
1481   "@
1482   add\\t%x0, %x1, %2
1483   add\\t%x0, %x1, %x2
1484   sub\\t%x0, %x1, #%n2
1485   add\\t%d0, %d1, %d2"
1486   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,neon_add")
1487    (set_attr "simd" "*,*,*,yes")]
1490 (define_expand "addti3"
1491   [(set (match_operand:TI 0 "register_operand" "")
1492         (plus:TI (match_operand:TI 1 "register_operand" "")
1493                  (match_operand:TI 2 "register_operand" "")))]
1494   ""
1496   rtx low = gen_reg_rtx (DImode);
1497   emit_insn (gen_adddi3_compare0 (low, gen_lowpart (DImode, operands[1]),
1498                                   gen_lowpart (DImode, operands[2])));
1500   rtx high = gen_reg_rtx (DImode);
1501   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1502                                  gen_highpart (DImode, operands[2])));
1504   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1505   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1506   DONE;
1509 (define_insn "add<mode>3_compare0"
1510   [(set (reg:CC_NZ CC_REGNUM)
1511         (compare:CC_NZ
1512          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1513                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1514          (const_int 0)))
1515    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1516         (plus:GPI (match_dup 1) (match_dup 2)))]
1517   ""
1518   "@
1519   adds\\t%<w>0, %<w>1, %<w>2
1520   adds\\t%<w>0, %<w>1, %<w>2
1521   subs\\t%<w>0, %<w>1, #%n2"
1522   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1525 ;; zero_extend version of above
1526 (define_insn "*addsi3_compare0_uxtw"
1527   [(set (reg:CC_NZ CC_REGNUM)
1528         (compare:CC_NZ
1529          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1530                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1531          (const_int 0)))
1532    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1533         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1534   ""
1535   "@
1536   adds\\t%w0, %w1, %w2
1537   adds\\t%w0, %w1, %w2
1538   subs\\t%w0, %w1, #%n2"
1539   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1542 (define_insn "*adds_mul_imm_<mode>"
1543   [(set (reg:CC_NZ CC_REGNUM)
1544         (compare:CC_NZ
1545          (plus:GPI (mult:GPI
1546                     (match_operand:GPI 1 "register_operand" "r")
1547                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1548                    (match_operand:GPI 3 "register_operand" "r"))
1549          (const_int 0)))
1550    (set (match_operand:GPI 0 "register_operand" "=r")
1551         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1552                   (match_dup 3)))]
1553   ""
1554   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1555   [(set_attr "type" "alus_shift_imm")]
1558 (define_insn "*subs_mul_imm_<mode>"
1559   [(set (reg:CC_NZ CC_REGNUM)
1560         (compare:CC_NZ
1561          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1562                     (mult:GPI
1563                      (match_operand:GPI 2 "register_operand" "r")
1564                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1565          (const_int 0)))
1566    (set (match_operand:GPI 0 "register_operand" "=r")
1567         (minus:GPI (match_dup 1)
1568                    (mult:GPI (match_dup 2) (match_dup 3))))]
1569   ""
1570   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1571   [(set_attr "type" "alus_shift_imm")]
1574 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1575   [(set (reg:CC_NZ CC_REGNUM)
1576         (compare:CC_NZ
1577          (plus:GPI
1578           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1579           (match_operand:GPI 2 "register_operand" "r"))
1580         (const_int 0)))
1581    (set (match_operand:GPI 0 "register_operand" "=r")
1582         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1583   ""
1584   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1585   [(set_attr "type" "alus_ext")]
1588 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1589   [(set (reg:CC_NZ CC_REGNUM)
1590         (compare:CC_NZ
1591          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1592                     (ANY_EXTEND:GPI
1593                      (match_operand:ALLX 2 "register_operand" "r")))
1594         (const_int 0)))
1595    (set (match_operand:GPI 0 "register_operand" "=r")
1596         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1597   ""
1598   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1599   [(set_attr "type" "alus_ext")]
1602 (define_insn "*adds_<optab><mode>_multp2"
1603   [(set (reg:CC_NZ CC_REGNUM)
1604         (compare:CC_NZ
1605          (plus:GPI (ANY_EXTRACT:GPI
1606                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1607                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1608                     (match_operand 3 "const_int_operand" "n")
1609                     (const_int 0))
1610                    (match_operand:GPI 4 "register_operand" "r"))
1611         (const_int 0)))
1612    (set (match_operand:GPI 0 "register_operand" "=r")
1613         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1614                                    (match_dup 3)
1615                                    (const_int 0))
1616                   (match_dup 4)))]
1617   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1618   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1619   [(set_attr "type" "alus_ext")]
1622 (define_insn "*subs_<optab><mode>_multp2"
1623   [(set (reg:CC_NZ CC_REGNUM)
1624         (compare:CC_NZ
1625          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1626                     (ANY_EXTRACT:GPI
1627                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1628                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1629                      (match_operand 3 "const_int_operand" "n")
1630                      (const_int 0)))
1631         (const_int 0)))
1632    (set (match_operand:GPI 0 "register_operand" "=r")
1633         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
1634                                   (mult:GPI (match_dup 1) (match_dup 2))
1635                                   (match_dup 3)
1636                                   (const_int 0))))]
1637   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1638   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1639   [(set_attr "type" "alus_ext")]
1642 (define_insn "*add<mode>3nr_compare0"
1643   [(set (reg:CC_NZ CC_REGNUM)
1644         (compare:CC_NZ
1645          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
1646                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
1647          (const_int 0)))]
1648   ""
1649   "@
1650   cmn\\t%<w>0, %<w>1
1651   cmn\\t%<w>0, %<w>1
1652   cmp\\t%<w>0, #%n1"
1653   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1656 (define_insn "*compare_neg<mode>"
1657   [(set (reg:CC_Z CC_REGNUM)
1658         (compare:CC_Z
1659          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
1660          (match_operand:GPI 1 "register_operand" "r")))]
1661   ""
1662   "cmn\\t%<w>1, %<w>0"
1663   [(set_attr "type" "alus_sreg")]
1666 (define_insn "*add_<shift>_<mode>"
1667   [(set (match_operand:GPI 0 "register_operand" "=r")
1668         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
1669                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1670                   (match_operand:GPI 3 "register_operand" "r")))]
1671   ""
1672   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1673   [(set_attr "type" "alu_shift_imm")]
1676 ;; zero_extend version of above
1677 (define_insn "*add_<shift>_si_uxtw"
1678   [(set (match_operand:DI 0 "register_operand" "=r")
1679         (zero_extend:DI
1680          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
1681                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
1682                   (match_operand:SI 3 "register_operand" "r"))))]
1683   ""
1684   "add\\t%w0, %w3, %w1, <shift> %2"
1685   [(set_attr "type" "alu_shift_imm")]
1688 (define_insn "*add_mul_imm_<mode>"
1689   [(set (match_operand:GPI 0 "register_operand" "=r")
1690         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1691                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1692                   (match_operand:GPI 3 "register_operand" "r")))]
1693   ""
1694   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1695   [(set_attr "type" "alu_shift_imm")]
1698 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
1699   [(set (match_operand:GPI 0 "register_operand" "=rk")
1700         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1701                   (match_operand:GPI 2 "register_operand" "r")))]
1702   ""
1703   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1704   [(set_attr "type" "alu_ext")]
1707 ;; zero_extend version of above
1708 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
1709   [(set (match_operand:DI 0 "register_operand" "=rk")
1710         (zero_extend:DI
1711          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
1712                   (match_operand:GPI 2 "register_operand" "r"))))]
1713   ""
1714   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
1715   [(set_attr "type" "alu_ext")]
1718 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
1719   [(set (match_operand:GPI 0 "register_operand" "=rk")
1720         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
1721                                (match_operand:ALLX 1 "register_operand" "r"))
1722                               (match_operand 2 "aarch64_imm3" "Ui3"))
1723                   (match_operand:GPI 3 "register_operand" "r")))]
1724   ""
1725   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1726   [(set_attr "type" "alu_ext")]
1729 ;; zero_extend version of above
1730 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
1731   [(set (match_operand:DI 0 "register_operand" "=rk")
1732         (zero_extend:DI
1733          (plus:SI (ashift:SI (ANY_EXTEND:SI
1734                               (match_operand:SHORT 1 "register_operand" "r"))
1735                              (match_operand 2 "aarch64_imm3" "Ui3"))
1736                   (match_operand:SI 3 "register_operand" "r"))))]
1737   ""
1738   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
1739   [(set_attr "type" "alu_ext")]
1742 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
1743   [(set (match_operand:GPI 0 "register_operand" "=rk")
1744         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
1745                              (match_operand:ALLX 1 "register_operand" "r"))
1746                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1747                   (match_operand:GPI 3 "register_operand" "r")))]
1748   ""
1749   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
1750   [(set_attr "type" "alu_ext")]
1753 ;; zero_extend version of above
1754 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
1755   [(set (match_operand:DI 0 "register_operand" "=rk")
1756         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
1757                              (match_operand:SHORT 1 "register_operand" "r"))
1758                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1759                   (match_operand:SI 3 "register_operand" "r"))))]
1760   ""
1761   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
1762   [(set_attr "type" "alu_ext")]
1765 (define_insn "*add_<optab><mode>_multp2"
1766   [(set (match_operand:GPI 0 "register_operand" "=rk")
1767         (plus:GPI (ANY_EXTRACT:GPI
1768                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1769                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1770                    (match_operand 3 "const_int_operand" "n")
1771                    (const_int 0))
1772                   (match_operand:GPI 4 "register_operand" "r")))]
1773   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1774   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1775   [(set_attr "type" "alu_ext")]
1778 ;; zero_extend version of above
1779 (define_insn "*add_<optab>si_multp2_uxtw"
1780   [(set (match_operand:DI 0 "register_operand" "=rk")
1781         (zero_extend:DI
1782          (plus:SI (ANY_EXTRACT:SI
1783                    (mult:SI (match_operand:SI 1 "register_operand" "r")
1784                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1785                    (match_operand 3 "const_int_operand" "n")
1786                    (const_int 0))
1787                   (match_operand:SI 4 "register_operand" "r"))))]
1788   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
1789   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
1790   [(set_attr "type" "alu_ext")]
1793 (define_insn "add<mode>3_carryin"
1794   [(set
1795     (match_operand:GPI 0 "register_operand" "=r")
1796     (plus:GPI (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1797               (plus:GPI
1798                 (match_operand:GPI 1 "register_operand" "r")
1799                 (match_operand:GPI 2 "register_operand" "r"))))]
1800    ""
1801    "adc\\t%<w>0, %<w>1, %<w>2"
1802   [(set_attr "type" "adc_reg")]
1805 ;; zero_extend version of above
1806 (define_insn "*addsi3_carryin_uxtw"
1807   [(set
1808     (match_operand:DI 0 "register_operand" "=r")
1809     (zero_extend:DI
1810      (plus:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
1811               (plus:SI
1812                (match_operand:SI 1 "register_operand" "r")
1813                (match_operand:SI 2 "register_operand" "r")))))]
1814    ""
1815    "adc\\t%w0, %w1, %w2"
1816   [(set_attr "type" "adc_reg")]
1819 (define_insn "*add<mode>3_carryin_alt1"
1820   [(set
1821     (match_operand:GPI 0 "register_operand" "=r")
1822     (plus:GPI (plus:GPI
1823                 (match_operand:GPI 1 "register_operand" "r")
1824                 (match_operand:GPI 2 "register_operand" "r"))
1825               (geu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
1826    ""
1827    "adc\\t%<w>0, %<w>1, %<w>2"
1828   [(set_attr "type" "adc_reg")]
1831 ;; zero_extend version of above
1832 (define_insn "*addsi3_carryin_alt1_uxtw"
1833   [(set
1834     (match_operand:DI 0 "register_operand" "=r")
1835     (zero_extend:DI
1836      (plus:SI (plus:SI
1837                (match_operand:SI 1 "register_operand" "r")
1838                (match_operand:SI 2 "register_operand" "r"))
1839               (geu:SI (reg:CC CC_REGNUM) (const_int 0)))))]
1840    ""
1841    "adc\\t%w0, %w1, %w2"
1842   [(set_attr "type" "adc_reg")]
1845 (define_insn "*add<mode>3_carryin_alt2"
1846   [(set
1847     (match_operand:GPI 0 "register_operand" "=r")
1848     (plus:GPI (plus:GPI
1849                 (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1850                 (match_operand:GPI 1 "register_operand" "r"))
1851               (match_operand:GPI 2 "register_operand" "r")))]
1852    ""
1853    "adc\\t%<w>0, %<w>1, %<w>2"
1854   [(set_attr "type" "adc_reg")]
1857 ;; zero_extend version of above
1858 (define_insn "*addsi3_carryin_alt2_uxtw"
1859   [(set
1860     (match_operand:DI 0 "register_operand" "=r")
1861     (zero_extend:DI
1862      (plus:SI (plus:SI
1863                (geu:SI (reg:CC CC_REGNUM) (const_int 0))
1864                (match_operand:SI 1 "register_operand" "r"))
1865               (match_operand:SI 2 "register_operand" "r"))))]
1866    ""
1867    "adc\\t%w0, %w1, %w2"
1868   [(set_attr "type" "adc_reg")]
1871 (define_insn "*add<mode>3_carryin_alt3"
1872   [(set
1873     (match_operand:GPI 0 "register_operand" "=r")
1874     (plus:GPI (plus:GPI
1875                 (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1876                 (match_operand:GPI 2 "register_operand" "r"))
1877               (match_operand:GPI 1 "register_operand" "r")))]
1878    ""
1879    "adc\\t%<w>0, %<w>1, %<w>2"
1880   [(set_attr "type" "adc_reg")]
1883 ;; zero_extend version of above
1884 (define_insn "*addsi3_carryin_alt3_uxtw"
1885   [(set
1886     (match_operand:DI 0 "register_operand" "=r")
1887     (zero_extend:DI
1888      (plus:SI (plus:SI
1889                (geu:SI (reg:CC CC_REGNUM) (const_int 0))
1890                (match_operand:SI 2 "register_operand" "r"))
1891               (match_operand:SI 1 "register_operand" "r"))))]
1892    ""
1893    "adc\\t%w0, %w1, %w2"
1894   [(set_attr "type" "adc_reg")]
1897 (define_insn "*add_uxt<mode>_multp2"
1898   [(set (match_operand:GPI 0 "register_operand" "=rk")
1899         (plus:GPI (and:GPI
1900                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1901                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1902                    (match_operand 3 "const_int_operand" "n"))
1903                   (match_operand:GPI 4 "register_operand" "r")))]
1904   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
1905   "*
1906   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1907                                            INTVAL (operands[3])));
1908   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
1909   [(set_attr "type" "alu_ext")]
1912 ;; zero_extend version of above
1913 (define_insn "*add_uxtsi_multp2_uxtw"
1914   [(set (match_operand:DI 0 "register_operand" "=rk")
1915         (zero_extend:DI
1916          (plus:SI (and:SI
1917                    (mult:SI (match_operand:SI 1 "register_operand" "r")
1918                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1919                    (match_operand 3 "const_int_operand" "n"))
1920                   (match_operand:SI 4 "register_operand" "r"))))]
1921   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
1922   "*
1923   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1924                                            INTVAL (operands[3])));
1925   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
1926   [(set_attr "type" "alu_ext")]
1929 (define_insn "subsi3"
1930   [(set (match_operand:SI 0 "register_operand" "=rk")
1931         (minus:SI (match_operand:SI 1 "register_operand" "rk")
1932                   (match_operand:SI 2 "register_operand" "r")))]
1933   ""
1934   "sub\\t%w0, %w1, %w2"
1935   [(set_attr "type" "alu_sreg")]
1938 ;; zero_extend version of above
1939 (define_insn "*subsi3_uxtw"
1940   [(set (match_operand:DI 0 "register_operand" "=rk")
1941         (zero_extend:DI
1942          (minus:SI (match_operand:SI 1 "register_operand" "rk")
1943                    (match_operand:SI 2 "register_operand" "r"))))]
1944   ""
1945   "sub\\t%w0, %w1, %w2"
1946   [(set_attr "type" "alu_sreg")]
1949 (define_insn "subdi3"
1950   [(set (match_operand:DI 0 "register_operand" "=rk,w")
1951         (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
1952                   (match_operand:DI 2 "register_operand" "r,w")))]
1953   ""
1954   "@
1955    sub\\t%x0, %x1, %x2
1956    sub\\t%d0, %d1, %d2"
1957   [(set_attr "type" "alu_sreg, neon_sub")
1958    (set_attr "simd" "*,yes")]
1961 (define_expand "subti3"
1962   [(set (match_operand:TI 0 "register_operand" "")
1963         (minus:TI (match_operand:TI 1 "register_operand" "")
1964                   (match_operand:TI 2 "register_operand" "")))]
1965   ""
1967   rtx low = gen_reg_rtx (DImode);
1968   emit_insn (gen_subdi3_compare0 (low, gen_lowpart (DImode, operands[1]),
1969                                   gen_lowpart (DImode, operands[2])));
1971   rtx high = gen_reg_rtx (DImode);
1972   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
1973                                  gen_highpart (DImode, operands[2])));
1975   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1976   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1977   DONE;
1980 (define_insn "sub<mode>3_compare0"
1981   [(set (reg:CC_NZ CC_REGNUM)
1982         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1983                                   (match_operand:GPI 2 "register_operand" "r"))
1984                        (const_int 0)))
1985    (set (match_operand:GPI 0 "register_operand" "=r")
1986         (minus:GPI (match_dup 1) (match_dup 2)))]
1987   ""
1988   "subs\\t%<w>0, %<w>1, %<w>2"
1989   [(set_attr "type" "alus_sreg")]
1992 ;; zero_extend version of above
1993 (define_insn "*subsi3_compare0_uxtw"
1994   [(set (reg:CC_NZ CC_REGNUM)
1995         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
1996                                  (match_operand:SI 2 "register_operand" "r"))
1997                        (const_int 0)))
1998    (set (match_operand:DI 0 "register_operand" "=r")
1999         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2000   ""
2001   "subs\\t%w0, %w1, %w2"
2002   [(set_attr "type" "alus_sreg")]
2005 (define_insn "*sub_<shift>_<mode>"
2006   [(set (match_operand:GPI 0 "register_operand" "=r")
2007         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2008                    (ASHIFT:GPI
2009                     (match_operand:GPI 1 "register_operand" "r")
2010                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2011   ""
2012   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2013   [(set_attr "type" "alu_shift_imm")]
2016 ;; zero_extend version of above
2017 (define_insn "*sub_<shift>_si_uxtw"
2018   [(set (match_operand:DI 0 "register_operand" "=r")
2019         (zero_extend:DI
2020          (minus:SI (match_operand:SI 3 "register_operand" "r")
2021                    (ASHIFT:SI
2022                     (match_operand:SI 1 "register_operand" "r")
2023                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2024   ""
2025   "sub\\t%w0, %w3, %w1, <shift> %2"
2026   [(set_attr "type" "alu_shift_imm")]
2029 (define_insn "*sub_mul_imm_<mode>"
2030   [(set (match_operand:GPI 0 "register_operand" "=r")
2031         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2032                    (mult:GPI
2033                     (match_operand:GPI 1 "register_operand" "r")
2034                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2035   ""
2036   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2037   [(set_attr "type" "alu_shift_imm")]
2040 ;; zero_extend version of above
2041 (define_insn "*sub_mul_imm_si_uxtw"
2042   [(set (match_operand:DI 0 "register_operand" "=r")
2043         (zero_extend:DI
2044          (minus:SI (match_operand:SI 3 "register_operand" "r")
2045                    (mult:SI
2046                     (match_operand:SI 1 "register_operand" "r")
2047                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2048   ""
2049   "sub\\t%w0, %w3, %w1, lsl %p2"
2050   [(set_attr "type" "alu_shift_imm")]
2053 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2054   [(set (match_operand:GPI 0 "register_operand" "=rk")
2055         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2056                    (ANY_EXTEND:GPI
2057                     (match_operand:ALLX 2 "register_operand" "r"))))]
2058   ""
2059   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2060   [(set_attr "type" "alu_ext")]
2063 ;; zero_extend version of above
2064 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2065   [(set (match_operand:DI 0 "register_operand" "=rk")
2066         (zero_extend:DI
2067          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2068                    (ANY_EXTEND:SI
2069                     (match_operand:SHORT 2 "register_operand" "r")))))]
2070   ""
2071   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2072   [(set_attr "type" "alu_ext")]
2075 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2076   [(set (match_operand:GPI 0 "register_operand" "=rk")
2077         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2078                    (ashift:GPI (ANY_EXTEND:GPI
2079                                 (match_operand:ALLX 2 "register_operand" "r"))
2080                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
2081   ""
2082   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2083   [(set_attr "type" "alu_ext")]
2086 ;; zero_extend version of above
2087 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2088   [(set (match_operand:DI 0 "register_operand" "=rk")
2089         (zero_extend:DI
2090          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2091                    (ashift:SI (ANY_EXTEND:SI
2092                                (match_operand:SHORT 2 "register_operand" "r"))
2093                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
2094   ""
2095   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2096   [(set_attr "type" "alu_ext")]
2099 (define_insn "*sub_<optab><mode>_multp2"
2100   [(set (match_operand:GPI 0 "register_operand" "=rk")
2101         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2102                    (ANY_EXTRACT:GPI
2103                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2104                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2105                     (match_operand 3 "const_int_operand" "n")
2106                     (const_int 0))))]
2107   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2108   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2109   [(set_attr "type" "alu_ext")]
2112 ;; zero_extend version of above
2113 (define_insn "*sub_<optab>si_multp2_uxtw"
2114   [(set (match_operand:DI 0 "register_operand" "=rk")
2115         (zero_extend:DI
2116          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2117                    (ANY_EXTRACT:SI
2118                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2119                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2120                     (match_operand 3 "const_int_operand" "n")
2121                     (const_int 0)))))]
2122   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2123   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2124   [(set_attr "type" "alu_ext")]
2127 (define_insn "sub<mode>3_carryin"
2128   [(set
2129     (match_operand:GPI 0 "register_operand" "=r")
2130     (minus:GPI (minus:GPI
2131                 (match_operand:GPI 1 "register_operand" "r")
2132                 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0)))
2133                (match_operand:GPI 2 "register_operand" "r")))]
2134    ""
2135    "sbc\\t%<w>0, %<w>1, %<w>2"
2136   [(set_attr "type" "adc_reg")]
2139 ;; zero_extend version of the above
2140 (define_insn "*subsi3_carryin_uxtw"
2141   [(set
2142     (match_operand:DI 0 "register_operand" "=r")
2143     (zero_extend:DI
2144      (minus:SI (minus:SI
2145                 (match_operand:SI 1 "register_operand" "r")
2146                 (ltu:SI (reg:CC CC_REGNUM) (const_int 0)))
2147                (match_operand:SI 2 "register_operand" "r"))))]
2148    ""
2149    "sbc\\t%w0, %w1, %w2"
2150   [(set_attr "type" "adc_reg")]
2153 (define_insn "*sub_uxt<mode>_multp2"
2154   [(set (match_operand:GPI 0 "register_operand" "=rk")
2155         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2156                    (and:GPI
2157                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2158                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2159                     (match_operand 3 "const_int_operand" "n"))))]
2160   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2161   "*
2162   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2163                                            INTVAL (operands[3])));
2164   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2165   [(set_attr "type" "alu_ext")]
2168 ;; zero_extend version of above
2169 (define_insn "*sub_uxtsi_multp2_uxtw"
2170   [(set (match_operand:DI 0 "register_operand" "=rk")
2171         (zero_extend:DI
2172          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2173                    (and:SI
2174                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2175                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2176                     (match_operand 3 "const_int_operand" "n")))))]
2177   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2178   "*
2179   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2180                                            INTVAL (operands[3])));
2181   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2182   [(set_attr "type" "alu_ext")]
2185 (define_insn_and_split "absdi2"
2186   [(set (match_operand:DI 0 "register_operand" "=&r,w")
2187         (abs:DI (match_operand:DI 1 "register_operand" "r,w")))]
2188   ""
2189   "@
2190    #
2191    abs\\t%d0, %d1"
2192   "reload_completed
2193    && GP_REGNUM_P (REGNO (operands[0]))
2194    && GP_REGNUM_P (REGNO (operands[1]))"
2195   [(const_int 0)]
2196   {
2197     emit_insn (gen_rtx_SET (operands[0],
2198                             gen_rtx_XOR (DImode,
2199                                          gen_rtx_ASHIFTRT (DImode,
2200                                                            operands[1],
2201                                                            GEN_INT (63)),
2202                                          operands[1])));
2203     emit_insn (gen_rtx_SET (operands[0],
2204                             gen_rtx_MINUS (DImode,
2205                                            operands[0],
2206                                            gen_rtx_ASHIFTRT (DImode,
2207                                                              operands[1],
2208                                                              GEN_INT (63)))));
2209     DONE;
2210   }
2211   [(set_attr "type" "alu_sreg")
2212    (set_attr "simd" "no,yes")]
2215 (define_insn "neg<mode>2"
2216   [(set (match_operand:GPI 0 "register_operand" "=r,w")
2217         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2218   ""
2219   "@
2220    neg\\t%<w>0, %<w>1
2221    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2222   [(set_attr "type" "alu_sreg, neon_neg<q>")
2223    (set_attr "simd" "*,yes")]
2226 ;; zero_extend version of above
2227 (define_insn "*negsi2_uxtw"
2228   [(set (match_operand:DI 0 "register_operand" "=r")
2229         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2230   ""
2231   "neg\\t%w0, %w1"
2232   [(set_attr "type" "alu_sreg")]
2235 (define_insn "*ngc<mode>"
2236   [(set (match_operand:GPI 0 "register_operand" "=r")
2237         (minus:GPI (neg:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0)))
2238                    (match_operand:GPI 1 "register_operand" "r")))]
2239   ""
2240   "ngc\\t%<w>0, %<w>1"
2241   [(set_attr "type" "adc_reg")]
2244 (define_insn "*ngcsi_uxtw"
2245   [(set (match_operand:DI 0 "register_operand" "=r")
2246         (zero_extend:DI
2247          (minus:SI (neg:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0)))
2248                    (match_operand:SI 1 "register_operand" "r"))))]
2249   ""
2250   "ngc\\t%w0, %w1"
2251   [(set_attr "type" "adc_reg")]
2254 (define_insn "*neg<mode>2_compare0"
2255   [(set (reg:CC_NZ CC_REGNUM)
2256         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2257                        (const_int 0)))
2258    (set (match_operand:GPI 0 "register_operand" "=r")
2259         (neg:GPI (match_dup 1)))]
2260   ""
2261   "negs\\t%<w>0, %<w>1"
2262   [(set_attr "type" "alus_sreg")]
2265 ;; zero_extend version of above
2266 (define_insn "*negsi2_compare0_uxtw"
2267   [(set (reg:CC_NZ CC_REGNUM)
2268         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2269                        (const_int 0)))
2270    (set (match_operand:DI 0 "register_operand" "=r")
2271         (zero_extend:DI (neg:SI (match_dup 1))))]
2272   ""
2273   "negs\\t%w0, %w1"
2274   [(set_attr "type" "alus_sreg")]
2277 (define_insn "*neg_<shift><mode>3_compare0"
2278   [(set (reg:CC_NZ CC_REGNUM)
2279         (compare:CC_NZ
2280          (neg:GPI (ASHIFT:GPI
2281                    (match_operand:GPI 1 "register_operand" "r")
2282                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2283          (const_int 0)))
2284    (set (match_operand:GPI 0 "register_operand" "=r")
2285         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2286   ""
2287   "negs\\t%<w>0, %<w>1, <shift> %2"
2288   [(set_attr "type" "alus_shift_imm")]
2291 (define_insn "*neg_<shift>_<mode>2"
2292   [(set (match_operand:GPI 0 "register_operand" "=r")
2293         (neg:GPI (ASHIFT:GPI
2294                   (match_operand:GPI 1 "register_operand" "r")
2295                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2296   ""
2297   "neg\\t%<w>0, %<w>1, <shift> %2"
2298   [(set_attr "type" "alu_shift_imm")]
2301 ;; zero_extend version of above
2302 (define_insn "*neg_<shift>_si2_uxtw"
2303   [(set (match_operand:DI 0 "register_operand" "=r")
2304         (zero_extend:DI
2305          (neg:SI (ASHIFT:SI
2306                   (match_operand:SI 1 "register_operand" "r")
2307                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2308   ""
2309   "neg\\t%w0, %w1, <shift> %2"
2310   [(set_attr "type" "alu_shift_imm")]
2313 (define_insn "*neg_mul_imm_<mode>2"
2314   [(set (match_operand:GPI 0 "register_operand" "=r")
2315         (neg:GPI (mult:GPI
2316                   (match_operand:GPI 1 "register_operand" "r")
2317                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2318   ""
2319   "neg\\t%<w>0, %<w>1, lsl %p2"
2320   [(set_attr "type" "alu_shift_imm")]
2323 ;; zero_extend version of above
2324 (define_insn "*neg_mul_imm_si2_uxtw"
2325   [(set (match_operand:DI 0 "register_operand" "=r")
2326         (zero_extend:DI
2327          (neg:SI (mult:SI
2328                   (match_operand:SI 1 "register_operand" "r")
2329                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2330   ""
2331   "neg\\t%w0, %w1, lsl %p2"
2332   [(set_attr "type" "alu_shift_imm")]
2335 (define_insn "mul<mode>3"
2336   [(set (match_operand:GPI 0 "register_operand" "=r")
2337         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2338                   (match_operand:GPI 2 "register_operand" "r")))]
2339   ""
2340   "mul\\t%<w>0, %<w>1, %<w>2"
2341   [(set_attr "type" "mul")]
2344 ;; zero_extend version of above
2345 (define_insn "*mulsi3_uxtw"
2346   [(set (match_operand:DI 0 "register_operand" "=r")
2347         (zero_extend:DI
2348          (mult:SI (match_operand:SI 1 "register_operand" "r")
2349                   (match_operand:SI 2 "register_operand" "r"))))]
2350   ""
2351   "mul\\t%w0, %w1, %w2"
2352   [(set_attr "type" "mul")]
2355 (define_insn "madd<mode>"
2356   [(set (match_operand:GPI 0 "register_operand" "=r")
2357         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2358                             (match_operand:GPI 2 "register_operand" "r"))
2359                   (match_operand:GPI 3 "register_operand" "r")))]
2360   ""
2361   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2362   [(set_attr "type" "mla")]
2365 ;; zero_extend version of above
2366 (define_insn "*maddsi_uxtw"
2367   [(set (match_operand:DI 0 "register_operand" "=r")
2368         (zero_extend:DI
2369          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2370                            (match_operand:SI 2 "register_operand" "r"))
2371                   (match_operand:SI 3 "register_operand" "r"))))]
2372   ""
2373   "madd\\t%w0, %w1, %w2, %w3"
2374   [(set_attr "type" "mla")]
2377 (define_insn "*msub<mode>"
2378   [(set (match_operand:GPI 0 "register_operand" "=r")
2379         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2380                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2381                              (match_operand:GPI 2 "register_operand" "r"))))]
2383   ""
2384   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2385   [(set_attr "type" "mla")]
2388 ;; zero_extend version of above
2389 (define_insn "*msubsi_uxtw"
2390   [(set (match_operand:DI 0 "register_operand" "=r")
2391         (zero_extend:DI
2392          (minus:SI (match_operand:SI 3 "register_operand" "r")
2393                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2394                             (match_operand:SI 2 "register_operand" "r")))))]
2396   ""
2397   "msub\\t%w0, %w1, %w2, %w3"
2398   [(set_attr "type" "mla")]
2401 (define_insn "*mul<mode>_neg"
2402   [(set (match_operand:GPI 0 "register_operand" "=r")
2403         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2404                   (match_operand:GPI 2 "register_operand" "r")))]
2406   ""
2407   "mneg\\t%<w>0, %<w>1, %<w>2"
2408   [(set_attr "type" "mul")]
2411 ;; zero_extend version of above
2412 (define_insn "*mulsi_neg_uxtw"
2413   [(set (match_operand:DI 0 "register_operand" "=r")
2414         (zero_extend:DI
2415          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2416                   (match_operand:SI 2 "register_operand" "r"))))]
2418   ""
2419   "mneg\\t%w0, %w1, %w2"
2420   [(set_attr "type" "mul")]
2423 (define_insn "<su_optab>mulsidi3"
2424   [(set (match_operand:DI 0 "register_operand" "=r")
2425         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2426                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2427   ""
2428   "<su>mull\\t%0, %w1, %w2"
2429   [(set_attr "type" "<su>mull")]
2432 (define_insn "<su_optab>maddsidi4"
2433   [(set (match_operand:DI 0 "register_operand" "=r")
2434         (plus:DI (mult:DI
2435                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2436                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2437                  (match_operand:DI 3 "register_operand" "r")))]
2438   ""
2439   "<su>maddl\\t%0, %w1, %w2, %3"
2440   [(set_attr "type" "<su>mlal")]
2443 (define_insn "<su_optab>msubsidi4"
2444   [(set (match_operand:DI 0 "register_operand" "=r")
2445         (minus:DI
2446          (match_operand:DI 3 "register_operand" "r")
2447          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2448                   (ANY_EXTEND:DI
2449                    (match_operand:SI 2 "register_operand" "r")))))]
2450   ""
2451   "<su>msubl\\t%0, %w1, %w2, %3"
2452   [(set_attr "type" "<su>mlal")]
2455 (define_insn "*<su_optab>mulsidi_neg"
2456   [(set (match_operand:DI 0 "register_operand" "=r")
2457         (mult:DI (neg:DI
2458                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2459                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2460   ""
2461   "<su>mnegl\\t%0, %w1, %w2"
2462   [(set_attr "type" "<su>mull")]
2465 (define_expand "<su_optab>mulditi3"
2466   [(set (match_operand:TI 0 "register_operand")
2467         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2468                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2469   ""
2471   rtx low = gen_reg_rtx (DImode);
2472   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
2474   rtx high = gen_reg_rtx (DImode);
2475   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
2477   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2478   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2479   DONE;
2482 ;; The default expansion of multi3 using umuldi3_highpart will perform
2483 ;; the additions in an order that fails to combine into two madd insns.
2484 (define_expand "multi3"
2485   [(set (match_operand:TI 0 "register_operand")
2486         (mult:TI (match_operand:TI 1 "register_operand")
2487                  (match_operand:TI 2 "register_operand")))]
2488   ""
2490   rtx l0 = gen_reg_rtx (DImode);
2491   rtx l1 = gen_lowpart (DImode, operands[1]);
2492   rtx l2 = gen_lowpart (DImode, operands[2]);
2493   rtx h0 = gen_reg_rtx (DImode);
2494   rtx h1 = gen_highpart (DImode, operands[1]);
2495   rtx h2 = gen_highpart (DImode, operands[2]);
2497   emit_insn (gen_muldi3 (l0, l1, l2));
2498   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
2499   emit_insn (gen_madddi (h0, h1, l2, h0));
2500   emit_insn (gen_madddi (h0, l1, h2, h0));
2502   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
2503   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
2504   DONE;
2507 (define_insn "<su>muldi3_highpart"
2508   [(set (match_operand:DI 0 "register_operand" "=r")
2509         (truncate:DI
2510          (lshiftrt:TI
2511           (mult:TI
2512            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2513            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2514           (const_int 64))))]
2515   ""
2516   "<su>mulh\\t%0, %1, %2"
2517   [(set_attr "type" "<su>mull")]
2520 (define_insn "<su_optab>div<mode>3"
2521   [(set (match_operand:GPI 0 "register_operand" "=r")
2522         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2523                      (match_operand:GPI 2 "register_operand" "r")))]
2524   ""
2525   "<su>div\\t%<w>0, %<w>1, %<w>2"
2526   [(set_attr "type" "<su>div")]
2529 ;; zero_extend version of above
2530 (define_insn "*<su_optab>divsi3_uxtw"
2531   [(set (match_operand:DI 0 "register_operand" "=r")
2532         (zero_extend:DI
2533          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2534                      (match_operand:SI 2 "register_operand" "r"))))]
2535   ""
2536   "<su>div\\t%w0, %w1, %w2"
2537   [(set_attr "type" "<su>div")]
2540 ;; -------------------------------------------------------------------
2541 ;; Comparison insns
2542 ;; -------------------------------------------------------------------
2544 (define_insn "*cmp<mode>"
2545   [(set (reg:CC CC_REGNUM)
2546         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
2547                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
2548   ""
2549   "@
2550    cmp\\t%<w>0, %<w>1
2551    cmp\\t%<w>0, %<w>1
2552    cmn\\t%<w>0, #%n1"
2553   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2556 (define_insn "*cmp<mode>"
2557   [(set (reg:CCFP CC_REGNUM)
2558         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2559                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2560    "TARGET_FLOAT"
2561    "@
2562     fcmp\\t%<s>0, #0.0
2563     fcmp\\t%<s>0, %<s>1"
2564   [(set_attr "type" "fcmp<s>")]
2567 (define_insn "*cmpe<mode>"
2568   [(set (reg:CCFPE CC_REGNUM)
2569         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2570                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2571    "TARGET_FLOAT"
2572    "@
2573     fcmpe\\t%<s>0, #0.0
2574     fcmpe\\t%<s>0, %<s>1"
2575   [(set_attr "type" "fcmp<s>")]
2578 (define_insn "*cmp_swp_<shift>_reg<mode>"
2579   [(set (reg:CC_SWP CC_REGNUM)
2580         (compare:CC_SWP (ASHIFT:GPI
2581                          (match_operand:GPI 0 "register_operand" "r")
2582                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2583                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2584   ""
2585   "cmp\\t%<w>2, %<w>0, <shift> %1"
2586   [(set_attr "type" "alus_shift_imm")]
2589 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
2590   [(set (reg:CC_SWP CC_REGNUM)
2591         (compare:CC_SWP (ANY_EXTEND:GPI
2592                          (match_operand:ALLX 0 "register_operand" "r"))
2593                         (match_operand:GPI 1 "register_operand" "r")))]
2594   ""
2595   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
2596   [(set_attr "type" "alus_ext")]
2599 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
2600   [(set (reg:CC_SWP CC_REGNUM)
2601         (compare:CC_SWP (ashift:GPI
2602                          (ANY_EXTEND:GPI
2603                           (match_operand:ALLX 0 "register_operand" "r"))
2604                          (match_operand 1 "aarch64_imm3" "Ui3"))
2605         (match_operand:GPI 2 "register_operand" "r")))]
2606   ""
2607   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
2608   [(set_attr "type" "alus_ext")]
2611 ;; -------------------------------------------------------------------
2612 ;; Store-flag and conditional select insns
2613 ;; -------------------------------------------------------------------
2615 (define_expand "cstore<mode>4"
2616   [(set (match_operand:SI 0 "register_operand" "")
2617         (match_operator:SI 1 "aarch64_comparison_operator"
2618          [(match_operand:GPI 2 "register_operand" "")
2619           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
2620   ""
2621   "
2622   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2623                                       operands[3]);
2624   operands[3] = const0_rtx;
2625   "
2628 (define_expand "cstorecc4"
2629   [(set (match_operand:SI 0 "register_operand")
2630        (match_operator 1 "aarch64_comparison_operator"
2631         [(match_operand 2 "ccmp_cc_register")
2632          (match_operand 3 "const0_operand")]))]
2633   ""
2635   emit_insn (gen_rtx_SET (operands[0], operands[1]));
2636   DONE;
2640 (define_expand "cstore<mode>4"
2641   [(set (match_operand:SI 0 "register_operand" "")
2642         (match_operator:SI 1 "aarch64_comparison_operator"
2643          [(match_operand:GPF 2 "register_operand" "")
2644           (match_operand:GPF 3 "register_operand" "")]))]
2645   ""
2646   "
2647   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2648                                       operands[3]);
2649   operands[3] = const0_rtx;
2650   "
2653 (define_insn "*cstore<mode>_insn"
2654   [(set (match_operand:ALLI 0 "register_operand" "=r")
2655         (match_operator:ALLI 1 "aarch64_comparison_operator"
2656          [(match_operand 2 "cc_register" "") (const_int 0)]))]
2657   ""
2658   "cset\\t%<w>0, %m1"
2659   [(set_attr "type" "csel")]
2662 ;; zero_extend version of the above
2663 (define_insn "*cstoresi_insn_uxtw"
2664   [(set (match_operand:DI 0 "register_operand" "=r")
2665         (zero_extend:DI
2666          (match_operator:SI 1 "aarch64_comparison_operator"
2667           [(match_operand 2 "cc_register" "") (const_int 0)])))]
2668   ""
2669   "cset\\t%w0, %m1"
2670   [(set_attr "type" "csel")]
2673 (define_insn "cstore<mode>_neg"
2674   [(set (match_operand:ALLI 0 "register_operand" "=r")
2675         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator"
2676                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
2677   ""
2678   "csetm\\t%<w>0, %m1"
2679   [(set_attr "type" "csel")]
2682 ;; zero_extend version of the above
2683 (define_insn "*cstoresi_neg_uxtw"
2684   [(set (match_operand:DI 0 "register_operand" "=r")
2685         (zero_extend:DI
2686          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator"
2687                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
2688   ""
2689   "csetm\\t%w0, %m1"
2690   [(set_attr "type" "csel")]
2693 (define_expand "cmov<mode>6"
2694   [(set (match_operand:GPI 0 "register_operand" "")
2695         (if_then_else:GPI
2696          (match_operator 1 "aarch64_comparison_operator"
2697           [(match_operand:GPI 2 "register_operand" "")
2698            (match_operand:GPI 3 "aarch64_plus_operand" "")])
2699          (match_operand:GPI 4 "register_operand" "")
2700          (match_operand:GPI 5 "register_operand" "")))]
2701   ""
2702   "
2703   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2704                                       operands[3]);
2705   operands[3] = const0_rtx;
2706   "
2709 (define_expand "cmov<mode>6"
2710   [(set (match_operand:GPF 0 "register_operand" "")
2711         (if_then_else:GPF
2712          (match_operator 1 "aarch64_comparison_operator"
2713           [(match_operand:GPF 2 "register_operand" "")
2714            (match_operand:GPF 3 "register_operand" "")])
2715          (match_operand:GPF 4 "register_operand" "")
2716          (match_operand:GPF 5 "register_operand" "")))]
2717   ""
2718   "
2719   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2720                                       operands[3]);
2721   operands[3] = const0_rtx;
2722   "
2725 (define_insn "*cmov<mode>_insn"
2726   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
2727         (if_then_else:ALLI
2728          (match_operator 1 "aarch64_comparison_operator"
2729           [(match_operand 2 "cc_register" "") (const_int 0)])
2730          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
2731          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
2732   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
2733      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
2734   ;; Final two alternatives should be unreachable, but included for completeness
2735   "@
2736    csel\\t%<w>0, %<w>3, %<w>4, %m1
2737    csinv\\t%<w>0, %<w>3, <w>zr, %m1
2738    csinv\\t%<w>0, %<w>4, <w>zr, %M1
2739    csinc\\t%<w>0, %<w>3, <w>zr, %m1
2740    csinc\\t%<w>0, %<w>4, <w>zr, %M1
2741    mov\\t%<w>0, -1
2742    mov\\t%<w>0, 1"
2743   [(set_attr "type" "csel")]
2746 ;; zero_extend version of above
2747 (define_insn "*cmovsi_insn_uxtw"
2748   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
2749         (zero_extend:DI
2750          (if_then_else:SI
2751           (match_operator 1 "aarch64_comparison_operator"
2752            [(match_operand 2 "cc_register" "") (const_int 0)])
2753           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
2754           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
2755   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
2756      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
2757   ;; Final two alternatives should be unreachable, but included for completeness
2758   "@
2759    csel\\t%w0, %w3, %w4, %m1
2760    csinv\\t%w0, %w3, wzr, %m1
2761    csinv\\t%w0, %w4, wzr, %M1
2762    csinc\\t%w0, %w3, wzr, %m1
2763    csinc\\t%w0, %w4, wzr, %M1
2764    mov\\t%w0, -1
2765    mov\\t%w0, 1"
2766   [(set_attr "type" "csel")]
2769 (define_insn "*cmov<mode>_insn"
2770   [(set (match_operand:GPF 0 "register_operand" "=w")
2771         (if_then_else:GPF
2772          (match_operator 1 "aarch64_comparison_operator"
2773           [(match_operand 2 "cc_register" "") (const_int 0)])
2774          (match_operand:GPF 3 "register_operand" "w")
2775          (match_operand:GPF 4 "register_operand" "w")))]
2776   "TARGET_FLOAT"
2777   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
2778   [(set_attr "type" "fcsel")]
2781 (define_expand "mov<mode>cc"
2782   [(set (match_operand:ALLI 0 "register_operand" "")
2783         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
2784                            (match_operand:ALLI 2 "register_operand" "")
2785                            (match_operand:ALLI 3 "register_operand" "")))]
2786   ""
2787   {
2788     enum rtx_code code = GET_CODE (operands[1]);
2790     if (code == UNEQ || code == LTGT)
2791       FAIL;
2793     if (!ccmp_cc_register (XEXP (operands[1], 0),
2794                            GET_MODE (XEXP (operands[1], 0))))
2795       {
2796         rtx ccreg;
2797         ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
2798                                          XEXP (operands[1], 1));
2799         operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
2800       }
2801   }
2804 (define_expand "mov<GPF:mode><GPI:mode>cc"
2805   [(set (match_operand:GPI 0 "register_operand" "")
2806         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
2807                           (match_operand:GPF 2 "register_operand" "")
2808                           (match_operand:GPF 3 "register_operand" "")))]
2809   ""
2810   {
2811     rtx ccreg;
2812     enum rtx_code code = GET_CODE (operands[1]);
2814     if (code == UNEQ || code == LTGT)
2815       FAIL;
2817     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
2818                                   XEXP (operands[1], 1));
2819     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
2820   }
2823 (define_expand "mov<mode>cc"
2824   [(set (match_operand:GPF 0 "register_operand" "")
2825         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
2826                           (match_operand:GPF 2 "register_operand" "")
2827                           (match_operand:GPF 3 "register_operand" "")))]
2828   ""
2829   {
2830     rtx ccreg;
2831     enum rtx_code code = GET_CODE (operands[1]);
2833     if (code == UNEQ || code == LTGT)
2834       FAIL;
2836     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
2837                                   XEXP (operands[1], 1));
2838     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
2839   }
2843 ;; CRC32 instructions.
2844 (define_insn "aarch64_<crc_variant>"
2845   [(set (match_operand:SI 0 "register_operand" "=r")
2846         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2847                     (match_operand:<crc_mode> 2 "register_operand" "r")]
2848          CRC))]
2849   "TARGET_CRC32"
2850   {
2851     if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64)
2852       return "<crc_variant>\\t%w0, %w1, %x2";
2853     else
2854       return "<crc_variant>\\t%w0, %w1, %w2";
2855   }
2856   [(set_attr "type" "crc")]
2859 (define_insn "*csinc2<mode>_insn"
2860   [(set (match_operand:GPI 0 "register_operand" "=r")
2861         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
2862                   (match_operand:GPI 1 "register_operand" "r")))]
2863   ""
2864   "csinc\\t%<w>0, %<w>1, %<w>1, %M2"
2865   [(set_attr "type" "csel")]
2868 (define_insn "csinc3<mode>_insn"
2869   [(set (match_operand:GPI 0 "register_operand" "=r")
2870         (if_then_else:GPI
2871           (match_operand 1 "aarch64_comparison_operation" "")
2872           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
2873                     (const_int 1))
2874           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
2875   ""
2876   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
2877   [(set_attr "type" "csel")]
2880 (define_insn "*csinv3<mode>_insn"
2881   [(set (match_operand:GPI 0 "register_operand" "=r")
2882         (if_then_else:GPI
2883           (match_operand 1 "aarch64_comparison_operation" "")
2884           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
2885           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
2886   ""
2887   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
2888   [(set_attr "type" "csel")]
2891 (define_insn "*csneg3<mode>_insn"
2892   [(set (match_operand:GPI 0 "register_operand" "=r")
2893         (if_then_else:GPI
2894           (match_operand 1 "aarch64_comparison_operation" "")
2895           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
2896           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
2897   ""
2898   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
2899   [(set_attr "type" "csel")]
2902 ;; -------------------------------------------------------------------
2903 ;; Logical operations
2904 ;; -------------------------------------------------------------------
2906 (define_insn "<optab><mode>3"
2907   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
2908         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
2909                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
2910   ""
2911   "@
2912   <logical>\\t%<w>0, %<w>1, %<w>2
2913   <logical>\\t%<w>0, %<w>1, %<w>2
2914   <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
2915   [(set_attr "type" "logic_reg,logic_imm,neon_logic")
2916    (set_attr "simd" "*,*,yes")]
2919 ;; zero_extend version of above
2920 (define_insn "*<optab>si3_uxtw"
2921   [(set (match_operand:DI 0 "register_operand" "=r,rk")
2922         (zero_extend:DI
2923          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
2924                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
2925   ""
2926   "<logical>\\t%w0, %w1, %w2"
2927   [(set_attr "type" "logic_reg,logic_imm")]
2930 (define_insn "*and<mode>3_compare0"
2931   [(set (reg:CC_NZ CC_REGNUM)
2932         (compare:CC_NZ
2933          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
2934                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
2935          (const_int 0)))
2936    (set (match_operand:GPI 0 "register_operand" "=r,r")
2937         (and:GPI (match_dup 1) (match_dup 2)))]
2938   ""
2939   "ands\\t%<w>0, %<w>1, %<w>2"
2940   [(set_attr "type" "logics_reg,logics_imm")]
2943 ;; zero_extend version of above
2944 (define_insn "*andsi3_compare0_uxtw"
2945   [(set (reg:CC_NZ CC_REGNUM)
2946         (compare:CC_NZ
2947          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
2948                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
2949          (const_int 0)))
2950    (set (match_operand:DI 0 "register_operand" "=r,r")
2951         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
2952   ""
2953   "ands\\t%w0, %w1, %w2"
2954   [(set_attr "type" "logics_reg,logics_imm")]
2957 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
2958   [(set (reg:CC_NZ CC_REGNUM)
2959         (compare:CC_NZ
2960          (and:GPI (SHIFT:GPI
2961                    (match_operand:GPI 1 "register_operand" "r")
2962                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2963                   (match_operand:GPI 3 "register_operand" "r"))
2964          (const_int 0)))
2965    (set (match_operand:GPI 0 "register_operand" "=r")
2966         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
2967   ""
2968   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
2969   [(set_attr "type" "logics_shift_imm")]
2972 ;; zero_extend version of above
2973 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
2974   [(set (reg:CC_NZ CC_REGNUM)
2975         (compare:CC_NZ
2976          (and:SI (SHIFT:SI
2977                   (match_operand:SI 1 "register_operand" "r")
2978                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2979                  (match_operand:SI 3 "register_operand" "r"))
2980          (const_int 0)))
2981    (set (match_operand:DI 0 "register_operand" "=r")
2982         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
2983                                 (match_dup 3))))]
2984   ""
2985   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
2986   [(set_attr "type" "logics_shift_imm")]
2989 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
2990   [(set (match_operand:GPI 0 "register_operand" "=r")
2991         (LOGICAL:GPI (SHIFT:GPI
2992                       (match_operand:GPI 1 "register_operand" "r")
2993                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2994                      (match_operand:GPI 3 "register_operand" "r")))]
2995   ""
2996   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
2997   [(set_attr "type" "logic_shift_imm")]
3000 (define_insn "*<optab>_rol<mode>3"
3001   [(set (match_operand:GPI 0 "register_operand" "=r")
3002         (LOGICAL:GPI (rotate:GPI
3003                       (match_operand:GPI 1 "register_operand" "r")
3004                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3005                      (match_operand:GPI 3 "register_operand" "r")))]
3006   ""
3007   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3008   [(set_attr "type" "logic_shift_imm")]
3011 ;; zero_extend versions of above
3012 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3013   [(set (match_operand:DI 0 "register_operand" "=r")
3014         (zero_extend:DI
3015          (LOGICAL:SI (SHIFT:SI
3016                       (match_operand:SI 1 "register_operand" "r")
3017                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3018                      (match_operand:SI 3 "register_operand" "r"))))]
3019   ""
3020   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3021   [(set_attr "type" "logic_shift_imm")]
3024 (define_insn "*<optab>_rolsi3_uxtw"
3025   [(set (match_operand:DI 0 "register_operand" "=r")
3026         (zero_extend:DI
3027          (LOGICAL:SI (rotate:SI
3028                       (match_operand:SI 1 "register_operand" "r")
3029                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3030                      (match_operand:SI 3 "register_operand" "r"))))]
3031   ""
3032   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3033   [(set_attr "type" "logic_shift_imm")]
3036 (define_insn "one_cmpl<mode>2"
3037   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3038         (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3039   ""
3040   "@
3041   mvn\\t%<w>0, %<w>1
3042   mvn\\t%0.8b, %1.8b"
3043   [(set_attr "type" "logic_reg,neon_logic")
3044    (set_attr "simd" "*,yes")]
3047 (define_insn "*one_cmpl_<optab><mode>2"
3048   [(set (match_operand:GPI 0 "register_operand" "=r")
3049         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3050                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3051   ""
3052   "mvn\\t%<w>0, %<w>1, <shift> %2"
3053   [(set_attr "type" "logic_shift_imm")]
3056 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3058 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3059   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3060         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3061                      (match_operand:GPI 2 "register_operand" "r,w")))]
3062   ""
3063   "@
3064   <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3065   <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3066   [(set_attr "type" "logic_reg,neon_logic")
3067    (set_attr "simd" "*,yes")]
3070 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3071   [(set (match_operand:DI 0 "register_operand" "=r")
3072         (zero_extend:DI
3073           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3074                        (match_operand:SI 2 "register_operand" "r"))))]
3075   ""
3076   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3077   [(set_attr "type" "logic_reg")]
3080 (define_insn "*xor_one_cmplsidi3_ze"
3081   [(set (match_operand:DI 0 "register_operand" "=r")
3082         (zero_extend:DI
3083           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3084                           (match_operand:SI 2 "register_operand" "r")))))]
3085   ""
3086   "eon\\t%w0, %w1, %w2"
3087   [(set_attr "type" "logic_reg")]
3090 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3091 ;; eon does not operate on SIMD registers so the vector variant must be split.
3092 (define_insn_and_split "*xor_one_cmpl<mode>3"
3093   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3094         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3095                           (match_operand:GPI 2 "register_operand" "r,w"))))]
3096   ""
3097   "@
3098   eon\\t%<w>0, %<w>1, %<w>2
3099   #"
3100   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3101   [(set (match_operand:GPI 0 "register_operand" "=w")
3102         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3103                  (match_operand:GPI 2 "register_operand" "w")))
3104    (set (match_dup 0) (not:GPI (match_dup 0)))]
3105   ""
3106   [(set_attr "type" "logic_reg,multiple")
3107    (set_attr "simd" "*,yes")]
3110 (define_insn "*and_one_cmpl<mode>3_compare0"
3111   [(set (reg:CC_NZ CC_REGNUM)
3112         (compare:CC_NZ
3113          (and:GPI (not:GPI
3114                    (match_operand:GPI 1 "register_operand" "r"))
3115                   (match_operand:GPI 2 "register_operand" "r"))
3116          (const_int 0)))
3117    (set (match_operand:GPI 0 "register_operand" "=r")
3118         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3119   ""
3120   "bics\\t%<w>0, %<w>2, %<w>1"
3121   [(set_attr "type" "logics_reg")]
3124 ;; zero_extend version of above
3125 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3126   [(set (reg:CC_NZ CC_REGNUM)
3127         (compare:CC_NZ
3128          (and:SI (not:SI
3129                   (match_operand:SI 1 "register_operand" "r"))
3130                  (match_operand:SI 2 "register_operand" "r"))
3131          (const_int 0)))
3132    (set (match_operand:DI 0 "register_operand" "=r")
3133         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3134   ""
3135   "bics\\t%w0, %w2, %w1"
3136   [(set_attr "type" "logics_reg")]
3139 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3140   [(set (reg:CC_NZ CC_REGNUM)
3141     (compare:CC_NZ
3142      (and:GPI (not:GPI
3143            (match_operand:GPI 0 "register_operand" "r"))
3144           (match_operand:GPI 1 "register_operand" "r"))
3145      (const_int 0)))]
3146   ""
3147   "bics\\t<w>zr, %<w>1, %<w>0"
3148   [(set_attr "type" "logics_reg")]
3151 (define_insn "*<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3152   [(set (match_operand:GPI 0 "register_operand" "=r")
3153         (LOGICAL:GPI (not:GPI
3154                       (SHIFT:GPI
3155                        (match_operand:GPI 1 "register_operand" "r")
3156                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3157                      (match_operand:GPI 3 "register_operand" "r")))]
3158   ""
3159   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3160   [(set_attr "type" "logics_shift_imm")]
3163 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3164   [(set (match_operand:GPI 0 "register_operand" "=r")
3165         (not:GPI (xor:GPI
3166                       (SHIFT:GPI
3167                        (match_operand:GPI 1 "register_operand" "r")
3168                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3169                      (match_operand:GPI 3 "register_operand" "r"))))]
3170   ""
3171   "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3172   [(set_attr "type" "logic_shift_imm")]
3175 ;; Zero-extend version of the above.
3176 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3177   [(set (match_operand:DI 0 "register_operand" "=r")
3178         (zero_extend:DI
3179           (not:SI (xor:SI
3180                     (SHIFT:SI
3181                       (match_operand:SI 1 "register_operand" "r")
3182                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3183                     (match_operand:SI 3 "register_operand" "r")))))]
3184   ""
3185   "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3186   [(set_attr "type" "logic_shift_imm")]
3189 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3190   [(set (reg:CC_NZ CC_REGNUM)
3191         (compare:CC_NZ
3192          (and:GPI (not:GPI
3193                    (SHIFT:GPI
3194                     (match_operand:GPI 1 "register_operand" "r")
3195                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3196                   (match_operand:GPI 3 "register_operand" "r"))
3197          (const_int 0)))
3198    (set (match_operand:GPI 0 "register_operand" "=r")
3199         (and:GPI (not:GPI
3200                   (SHIFT:GPI
3201                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
3202   ""
3203   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3204   [(set_attr "type" "logics_shift_imm")]
3207 ;; zero_extend version of above
3208 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3209   [(set (reg:CC_NZ CC_REGNUM)
3210         (compare:CC_NZ
3211          (and:SI (not:SI
3212                   (SHIFT:SI
3213                    (match_operand:SI 1 "register_operand" "r")
3214                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3215                  (match_operand:SI 3 "register_operand" "r"))
3216          (const_int 0)))
3217    (set (match_operand:DI 0 "register_operand" "=r")
3218         (zero_extend:DI (and:SI
3219                          (not:SI
3220                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3221   ""
3222   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3223   [(set_attr "type" "logics_shift_imm")]
3226 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3227   [(set (reg:CC_NZ CC_REGNUM)
3228     (compare:CC_NZ
3229      (and:GPI (not:GPI
3230            (SHIFT:GPI
3231             (match_operand:GPI 0 "register_operand" "r")
3232             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3233           (match_operand:GPI 2 "register_operand" "r"))
3234      (const_int 0)))]
3235   ""
3236   "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3237   [(set_attr "type" "logics_shift_imm")]
3240 (define_insn "clz<mode>2"
3241   [(set (match_operand:GPI 0 "register_operand" "=r")
3242         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3243   ""
3244   "clz\\t%<w>0, %<w>1"
3245   [(set_attr "type" "clz")]
3248 (define_expand "ffs<mode>2"
3249   [(match_operand:GPI 0 "register_operand")
3250    (match_operand:GPI 1 "register_operand")]
3251   ""
3252   {
3253     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3254     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3256     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3257     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3258     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3259     DONE;
3260   }
3263 (define_insn "clrsb<mode>2"
3264   [(set (match_operand:GPI 0 "register_operand" "=r")
3265         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3266   ""
3267   "cls\\t%<w>0, %<w>1"
3268   [(set_attr "type" "clz")]
3271 (define_insn "rbit<mode>2"
3272   [(set (match_operand:GPI 0 "register_operand" "=r")
3273         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3274   ""
3275   "rbit\\t%<w>0, %<w>1"
3276   [(set_attr "type" "rbit")]
3279 (define_expand "ctz<mode>2"
3280   [(match_operand:GPI 0 "register_operand")
3281    (match_operand:GPI 1 "register_operand")]
3282   ""
3283   {
3284     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3285     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3286     DONE;
3287   }
3290 (define_insn "*and<mode>3nr_compare0"
3291   [(set (reg:CC_NZ CC_REGNUM)
3292         (compare:CC_NZ
3293          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
3294                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
3295          (const_int 0)))]
3296   ""
3297   "tst\\t%<w>0, %<w>1"
3298   [(set_attr "type" "logics_reg")]
3301 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
3302   [(set (reg:CC_NZ CC_REGNUM)
3303         (compare:CC_NZ
3304          (and:GPI (SHIFT:GPI
3305                    (match_operand:GPI 0 "register_operand" "r")
3306                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3307                   (match_operand:GPI 2 "register_operand" "r"))
3308         (const_int 0)))]
3309   ""
3310   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
3311   [(set_attr "type" "logics_shift_imm")]
3314 ;; -------------------------------------------------------------------
3315 ;; Shifts
3316 ;; -------------------------------------------------------------------
3318 (define_expand "<optab><mode>3"
3319   [(set (match_operand:GPI 0 "register_operand")
3320         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
3321                     (match_operand:QI 2 "nonmemory_operand")))]
3322   ""
3323   {
3324     if (CONST_INT_P (operands[2]))
3325       {
3326         operands[2] = GEN_INT (INTVAL (operands[2])
3327                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3329         if (operands[2] == const0_rtx)
3330           {
3331             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3332             DONE;
3333           }
3334       }
3335   }
3338 (define_expand "ashl<mode>3"
3339   [(set (match_operand:SHORT 0 "register_operand")
3340         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
3341                       (match_operand:QI 2 "nonmemory_operand")))]
3342   ""
3343   {
3344     if (CONST_INT_P (operands[2]))
3345       {
3346         operands[2] = GEN_INT (INTVAL (operands[2])
3347                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3349         if (operands[2] == const0_rtx)
3350           {
3351             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3352             DONE;
3353           }
3354       }
3355     else
3356       FAIL;
3357   }
3360 (define_expand "rotr<mode>3"
3361   [(set (match_operand:GPI 0 "register_operand")
3362         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3363                       (match_operand:QI 2 "nonmemory_operand")))]
3364   ""
3365   {
3366     if (CONST_INT_P (operands[2]))
3367       {
3368         operands[2] = GEN_INT (INTVAL (operands[2])
3369                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3371         if (operands[2] == const0_rtx)
3372           {
3373             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3374             DONE;
3375           }
3376       }
3377   }
3380 (define_expand "rotl<mode>3"
3381   [(set (match_operand:GPI 0 "register_operand")
3382         (rotatert:GPI (match_operand:GPI 1 "register_operand")
3383                       (match_operand:QI 2 "nonmemory_operand")))]
3384   ""
3385   {
3386     /* (SZ - cnt) % SZ == -cnt % SZ */
3387     if (CONST_INT_P (operands[2]))
3388       {
3389         operands[2] = GEN_INT ((-INTVAL (operands[2]))
3390                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
3391         if (operands[2] == const0_rtx)
3392           {
3393             emit_insn (gen_mov<mode> (operands[0], operands[1]));
3394             DONE;
3395           }
3396       }
3397     else
3398       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
3399                                         NULL_RTX, 1);
3400   }
3403 ;; Logical left shift using SISD or Integer instruction
3404 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
3405   [(set (match_operand:GPI 0 "register_operand" "=w,w,r")
3406         (ashift:GPI
3407           (match_operand:GPI 1 "register_operand" "w,w,r")
3408           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,w,rUs<cmode>")))]
3409   ""
3410   "@
3411    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3412    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
3413    lsl\t%<w>0, %<w>1, %<w>2"
3414   [(set_attr "simd" "yes,yes,no")
3415    (set_attr "type" "neon_shift_imm<q>, neon_shift_reg<q>,shift_reg")]
3418 ;; Logical right shift using SISD or Integer instruction
3419 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
3420   [(set (match_operand:GPI 0 "register_operand" "=w,&w,r")
3421         (lshiftrt:GPI
3422           (match_operand:GPI 1 "register_operand" "w,w,r")
3423           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,w,rUs<cmode>")))]
3424   ""
3425   "@
3426    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3427    #
3428    lsr\t%<w>0, %<w>1, %<w>2"
3429   [(set_attr "simd" "yes,yes,no")
3430    (set_attr "type" "neon_shift_imm<q>,neon_shift_reg<q>,shift_reg")]
3433 (define_split
3434   [(set (match_operand:DI 0 "aarch64_simd_register")
3435         (lshiftrt:DI
3436            (match_operand:DI 1 "aarch64_simd_register")
3437            (match_operand:QI 2 "aarch64_simd_register")))]
3438   "TARGET_SIMD && reload_completed"
3439   [(set (match_dup 3)
3440         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3441    (set (match_dup 0)
3442         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
3443   {
3444     operands[3] = gen_lowpart (QImode, operands[0]);
3445   }
3448 (define_split
3449   [(set (match_operand:SI 0 "aarch64_simd_register")
3450         (lshiftrt:SI
3451            (match_operand:SI 1 "aarch64_simd_register")
3452            (match_operand:QI 2 "aarch64_simd_register")))]
3453   "TARGET_SIMD && reload_completed"
3454   [(set (match_dup 3)
3455         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3456    (set (match_dup 0)
3457         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
3458   {
3459     operands[3] = gen_lowpart (QImode, operands[0]);
3460   }
3463 ;; Arithmetic right shift using SISD or Integer instruction
3464 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
3465   [(set (match_operand:GPI 0 "register_operand" "=w,&w,&w,r")
3466         (ashiftrt:GPI
3467           (match_operand:GPI 1 "register_operand" "w,w,w,r")
3468           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,w,0,rUs<cmode>")))]
3469   ""
3470   "@
3471    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
3472    #
3473    #
3474    asr\t%<w>0, %<w>1, %<w>2"
3475   [(set_attr "simd" "yes,yes,yes,no")
3476    (set_attr "type" "neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>,shift_reg")]
3479 (define_split
3480   [(set (match_operand:DI 0 "aarch64_simd_register")
3481         (ashiftrt:DI
3482            (match_operand:DI 1 "aarch64_simd_register")
3483            (match_operand:QI 2 "aarch64_simd_register")))]
3484   "TARGET_SIMD && reload_completed"
3485   [(set (match_dup 3)
3486         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3487    (set (match_dup 0)
3488         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
3490   operands[3] = gen_lowpart (QImode, operands[0]);
3494 (define_split
3495   [(set (match_operand:SI 0 "aarch64_simd_register")
3496         (ashiftrt:SI
3497            (match_operand:SI 1 "aarch64_simd_register")
3498            (match_operand:QI 2 "aarch64_simd_register")))]
3499   "TARGET_SIMD && reload_completed"
3500   [(set (match_dup 3)
3501         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
3502    (set (match_dup 0)
3503         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
3505   operands[3] = gen_lowpart (QImode, operands[0]);
3509 (define_insn "*aarch64_sisd_ushl"
3510   [(set (match_operand:DI 0 "register_operand" "=w")
3511         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
3512                     (match_operand:QI 2 "register_operand" "w")]
3513                    UNSPEC_SISD_USHL))]
3514   "TARGET_SIMD"
3515   "ushl\t%d0, %d1, %d2"
3516   [(set_attr "simd" "yes")
3517    (set_attr "type" "neon_shift_reg")]
3520 (define_insn "*aarch64_ushl_2s"
3521   [(set (match_operand:SI 0 "register_operand" "=w")
3522         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
3523                     (match_operand:QI 2 "register_operand" "w")]
3524                    UNSPEC_USHL_2S))]
3525   "TARGET_SIMD"
3526   "ushl\t%0.2s, %1.2s, %2.2s"
3527   [(set_attr "simd" "yes")
3528    (set_attr "type" "neon_shift_reg")]
3531 (define_insn "*aarch64_sisd_sshl"
3532   [(set (match_operand:DI 0 "register_operand" "=w")
3533         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
3534                     (match_operand:QI 2 "register_operand" "w")]
3535                    UNSPEC_SISD_SSHL))]
3536   "TARGET_SIMD"
3537   "sshl\t%d0, %d1, %d2"
3538   [(set_attr "simd" "yes")
3539    (set_attr "type" "neon_shift_reg")]
3542 (define_insn "*aarch64_sshl_2s"
3543   [(set (match_operand:SI 0 "register_operand" "=w")
3544         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
3545                     (match_operand:QI 2 "register_operand" "w")]
3546                    UNSPEC_SSHL_2S))]
3547   "TARGET_SIMD"
3548   "sshl\t%0.2s, %1.2s, %2.2s"
3549   [(set_attr "simd" "yes")
3550    (set_attr "type" "neon_shift_reg")]
3553 (define_insn "*aarch64_sisd_neg_qi"
3554   [(set (match_operand:QI 0 "register_operand" "=w")
3555         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
3556                    UNSPEC_SISD_NEG))]
3557   "TARGET_SIMD"
3558   "neg\t%d0, %d1"
3559   [(set_attr "simd" "yes")
3560    (set_attr "type" "neon_neg")]
3563 ;; Rotate right
3564 (define_insn "*ror<mode>3_insn"
3565   [(set (match_operand:GPI 0 "register_operand" "=r")
3566         (rotatert:GPI
3567           (match_operand:GPI 1 "register_operand" "r")
3568           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "rUs<cmode>")))]
3569   ""
3570   "ror\\t%<w>0, %<w>1, %<w>2"
3571   [(set_attr "type" "shift_reg")]
3574 ;; zero_extend version of above
3575 (define_insn "*<optab>si3_insn_uxtw"
3576   [(set (match_operand:DI 0 "register_operand" "=r")
3577         (zero_extend:DI (SHIFT:SI
3578          (match_operand:SI 1 "register_operand" "r")
3579          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "rUss"))))]
3580   ""
3581   "<shift>\\t%w0, %w1, %w2"
3582   [(set_attr "type" "shift_reg")]
3585 (define_insn "*<optab><mode>3_insn"
3586   [(set (match_operand:SHORT 0 "register_operand" "=r")
3587         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
3588                       (match_operand 2 "const_int_operand" "n")))]
3589   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
3591   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
3592   return "<bfshift>\t%w0, %w1, %2, %3";
3594   [(set_attr "type" "bfm")]
3597 (define_insn "*extr<mode>5_insn"
3598   [(set (match_operand:GPI 0 "register_operand" "=r")
3599         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3600                              (match_operand 3 "const_int_operand" "n"))
3601                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
3602                                (match_operand 4 "const_int_operand" "n"))))]
3603   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
3604    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
3605   "extr\\t%<w>0, %<w>1, %<w>2, %4"
3606   [(set_attr "type" "shift_imm")]
3609 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
3610 ;; so we have to match both orderings.
3611 (define_insn "*extr<mode>5_insn_alt"
3612   [(set (match_operand:GPI 0 "register_operand" "=r")
3613         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
3614                                 (match_operand 4 "const_int_operand" "n"))
3615                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3616                               (match_operand 3 "const_int_operand" "n"))))]
3617   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
3618    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
3619        == GET_MODE_BITSIZE (<MODE>mode))"
3620   "extr\\t%<w>0, %<w>1, %<w>2, %4"
3621   [(set_attr "type" "shift_imm")]
3624 ;; zero_extend version of the above
3625 (define_insn "*extrsi5_insn_uxtw"
3626   [(set (match_operand:DI 0 "register_operand" "=r")
3627         (zero_extend:DI
3628          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
3629                             (match_operand 3 "const_int_operand" "n"))
3630                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
3631                               (match_operand 4 "const_int_operand" "n")))))]
3632   "UINTVAL (operands[3]) < 32 &&
3633    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
3634   "extr\\t%w0, %w1, %w2, %4"
3635   [(set_attr "type" "shift_imm")]
3638 (define_insn "*extrsi5_insn_uxtw_alt"
3639   [(set (match_operand:DI 0 "register_operand" "=r")
3640         (zero_extend:DI
3641          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
3642                                (match_operand 4 "const_int_operand" "n"))
3643                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
3644                             (match_operand 3 "const_int_operand" "n")))))]
3645   "UINTVAL (operands[3]) < 32 &&
3646    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
3647   "extr\\t%w0, %w1, %w2, %4"
3648   [(set_attr "type" "shift_imm")]
3651 (define_insn "*ror<mode>3_insn"
3652   [(set (match_operand:GPI 0 "register_operand" "=r")
3653         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
3654                     (match_operand 2 "const_int_operand" "n")))]
3655   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
3657   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
3658   return "ror\\t%<w>0, %<w>1, %3";
3660   [(set_attr "type" "shift_imm")]
3663 ;; zero_extend version of the above
3664 (define_insn "*rorsi3_insn_uxtw"
3665   [(set (match_operand:DI 0 "register_operand" "=r")
3666         (zero_extend:DI
3667          (rotate:SI (match_operand:SI 1 "register_operand" "r")
3668                     (match_operand 2 "const_int_operand" "n"))))]
3669   "UINTVAL (operands[2]) < 32"
3671   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
3672   return "ror\\t%w0, %w1, %3";
3674   [(set_attr "type" "shift_imm")]
3677 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
3678   [(set (match_operand:GPI 0 "register_operand" "=r")
3679         (ANY_EXTEND:GPI
3680          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
3681                        (match_operand 2 "const_int_operand" "n"))))]
3682   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
3684   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
3685   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
3687   [(set_attr "type" "bfm")]
3690 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
3691   [(set (match_operand:GPI 0 "register_operand" "=r")
3692         (zero_extend:GPI
3693          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
3694                          (match_operand 2 "const_int_operand" "n"))))]
3695   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
3697   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
3698   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
3700   [(set_attr "type" "bfm")]
3703 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
3704   [(set (match_operand:GPI 0 "register_operand" "=r")
3705         (sign_extend:GPI
3706          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
3707                          (match_operand 2 "const_int_operand" "n"))))]
3708   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
3710   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
3711   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
3713   [(set_attr "type" "bfm")]
3716 ;; -------------------------------------------------------------------
3717 ;; Bitfields
3718 ;; -------------------------------------------------------------------
3720 (define_expand "<optab>"
3721   [(set (match_operand:DI 0 "register_operand" "=r")
3722         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand" "r")
3723                         (match_operand 2 "const_int_operand" "n")
3724                         (match_operand 3 "const_int_operand" "n")))]
3725   ""
3726   ""
3729 (define_insn "*<optab><mode>"
3730   [(set (match_operand:GPI 0 "register_operand" "=r")
3731         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
3732                          (match_operand 2 "const_int_operand" "n")
3733                          (match_operand 3 "const_int_operand" "n")))]
3734   ""
3735   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
3736   [(set_attr "type" "bfm")]
3739 ;; Bitfield Insert (insv)
3740 (define_expand "insv<mode>"
3741   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
3742                           (match_operand 1 "const_int_operand")
3743                           (match_operand 2 "const_int_operand"))
3744         (match_operand:GPI 3 "general_operand"))]
3745   ""
3747   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
3748   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
3749   rtx value = operands[3];
3751   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
3752     FAIL;
3754   if (CONST_INT_P (value))
3755     {
3756       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
3758       /* Prefer AND/OR for inserting all zeros or all ones.  */
3759       if ((UINTVAL (value) & mask) == 0
3760            || (UINTVAL (value) & mask) == mask)
3761         FAIL;
3763       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
3764       if (width == 16 && (pos % 16) == 0)
3765         DONE;
3766     }
3767   operands[3] = force_reg (<MODE>mode, value);
3770 (define_insn "*insv_reg<mode>"
3771   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
3772                           (match_operand 1 "const_int_operand" "n")
3773                           (match_operand 2 "const_int_operand" "n"))
3774         (match_operand:GPI 3 "register_operand" "r"))]
3775   "!(UINTVAL (operands[1]) == 0
3776      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
3777          > GET_MODE_BITSIZE (<MODE>mode)))"
3778   "bfi\\t%<w>0, %<w>3, %2, %1"
3779   [(set_attr "type" "bfm")]
3782 (define_insn "*extr_insv_lower_reg<mode>"
3783   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
3784                           (match_operand 1 "const_int_operand" "n")
3785                           (const_int 0))
3786         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
3787                           (match_dup 1)
3788                           (match_operand 3 "const_int_operand" "n")))]
3789   "!(UINTVAL (operands[1]) == 0
3790      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
3791          > GET_MODE_BITSIZE (<MODE>mode)))"
3792   "bfxil\\t%<w>0, %<w>2, %3, %1"
3793   [(set_attr "type" "bfm")]
3796 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
3797   [(set (match_operand:GPI 0 "register_operand" "=r")
3798         (ashift:GPI (ANY_EXTEND:GPI
3799                      (match_operand:ALLX 1 "register_operand" "r"))
3800                     (match_operand 2 "const_int_operand" "n")))]
3801   "UINTVAL (operands[2]) < <GPI:sizen>"
3803   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
3804               ? GEN_INT (<ALLX:sizen>)
3805               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
3806   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
3808   [(set_attr "type" "bfm")]
3811 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
3813 (define_insn "*andim_ashift<mode>_bfiz"
3814   [(set (match_operand:GPI 0 "register_operand" "=r")
3815         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3816                              (match_operand 2 "const_int_operand" "n"))
3817                  (match_operand 3 "const_int_operand" "n")))]
3818   "(INTVAL (operands[2]) < (<GPI:sizen>))
3819    && exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1) >= 0
3820    && (INTVAL (operands[3]) & ((1 << INTVAL (operands[2])) - 1)) == 0"
3821   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
3822   [(set_attr "type" "bfm")]
3825 (define_insn "bswap<mode>2"
3826   [(set (match_operand:GPI 0 "register_operand" "=r")
3827         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
3828   ""
3829   "rev\\t%<w>0, %<w>1"
3830   [(set_attr "type" "rev")]
3833 (define_insn "bswaphi2"
3834   [(set (match_operand:HI 0 "register_operand" "=r")
3835         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
3836   ""
3837   "rev16\\t%w0, %w1"
3838   [(set_attr "type" "rev")]
3841 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
3842 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
3843 ;; each valid permutation.
3845 (define_insn "rev16<mode>2"
3846   [(set (match_operand:GPI 0 "register_operand" "=r")
3847         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3848                                       (const_int 8))
3849                           (match_operand:GPI 3 "const_int_operand" "n"))
3850                  (and:GPI (lshiftrt:GPI (match_dup 1)
3851                                         (const_int 8))
3852                           (match_operand:GPI 2 "const_int_operand" "n"))))]
3853   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
3854    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
3855   "rev16\\t%<w>0, %<w>1"
3856   [(set_attr "type" "rev")]
3859 (define_insn "rev16<mode>2_alt"
3860   [(set (match_operand:GPI 0 "register_operand" "=r")
3861         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
3862                                         (const_int 8))
3863                           (match_operand:GPI 2 "const_int_operand" "n"))
3864                  (and:GPI (ashift:GPI (match_dup 1)
3865                                       (const_int 8))
3866                           (match_operand:GPI 3 "const_int_operand" "n"))))]
3867   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
3868    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
3869   "rev16\\t%<w>0, %<w>1"
3870   [(set_attr "type" "rev")]
3873 ;; zero_extend version of above
3874 (define_insn "*bswapsi2_uxtw"
3875   [(set (match_operand:DI 0 "register_operand" "=r")
3876         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
3877   ""
3878   "rev\\t%w0, %w1"
3879   [(set_attr "type" "rev")]
3882 ;; -------------------------------------------------------------------
3883 ;; Floating-point intrinsics
3884 ;; -------------------------------------------------------------------
3886 ;; frint floating-point round to integral standard patterns.
3887 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
3889 (define_insn "<frint_pattern><mode>2"
3890   [(set (match_operand:GPF 0 "register_operand" "=w")
3891         (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
3892          FRINT))]
3893   "TARGET_FLOAT"
3894   "frint<frint_suffix>\\t%<s>0, %<s>1"
3895   [(set_attr "type" "f_rint<s>")]
3898 ;; frcvt floating-point round to integer and convert standard patterns.
3899 ;; Expands to lbtrunc, lceil, lfloor, lround.
3900 (define_insn "l<fcvt_pattern><su_optab><GPF:mode><GPI:mode>2"
3901   [(set (match_operand:GPI 0 "register_operand" "=r")
3902         (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
3903                       FCVT)))]
3904   "TARGET_FLOAT"
3905   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF:s>1"
3906   [(set_attr "type" "f_cvtf2i")]
3909 ;; fma - no throw
3911 (define_insn "fma<mode>4"
3912   [(set (match_operand:GPF 0 "register_operand" "=w")
3913         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
3914                  (match_operand:GPF 2 "register_operand" "w")
3915                  (match_operand:GPF 3 "register_operand" "w")))]
3916   "TARGET_FLOAT"
3917   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
3918   [(set_attr "type" "fmac<s>")]
3921 (define_insn "fnma<mode>4"
3922   [(set (match_operand:GPF 0 "register_operand" "=w")
3923         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
3924                  (match_operand:GPF 2 "register_operand" "w")
3925                  (match_operand:GPF 3 "register_operand" "w")))]
3926   "TARGET_FLOAT"
3927   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
3928   [(set_attr "type" "fmac<s>")]
3931 (define_insn "fms<mode>4"
3932   [(set (match_operand:GPF 0 "register_operand" "=w")
3933         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
3934                  (match_operand:GPF 2 "register_operand" "w")
3935                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
3936   "TARGET_FLOAT"
3937   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
3938   [(set_attr "type" "fmac<s>")]
3941 (define_insn "fnms<mode>4"
3942   [(set (match_operand:GPF 0 "register_operand" "=w")
3943         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
3944                  (match_operand:GPF 2 "register_operand" "w")
3945                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
3946   "TARGET_FLOAT"
3947   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
3948   [(set_attr "type" "fmac<s>")]
3951 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
3952 (define_insn "*fnmadd<mode>4"
3953   [(set (match_operand:GPF 0 "register_operand" "=w")
3954         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
3955                           (match_operand:GPF 2 "register_operand" "w")
3956                           (match_operand:GPF 3 "register_operand" "w"))))]
3957   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
3958   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
3959   [(set_attr "type" "fmac<s>")]
3962 ;; -------------------------------------------------------------------
3963 ;; Floating-point conversions
3964 ;; -------------------------------------------------------------------
3966 (define_insn "extendsfdf2"
3967   [(set (match_operand:DF 0 "register_operand" "=w")
3968         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
3969   "TARGET_FLOAT"
3970   "fcvt\\t%d0, %s1"
3971   [(set_attr "type" "f_cvt")]
3974 (define_insn "truncdfsf2"
3975   [(set (match_operand:SF 0 "register_operand" "=w")
3976         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
3977   "TARGET_FLOAT"
3978   "fcvt\\t%s0, %d1"
3979   [(set_attr "type" "f_cvt")]
3982 (define_insn "fix_trunc<GPF:mode><GPI:mode>2"
3983   [(set (match_operand:GPI 0 "register_operand" "=r")
3984         (fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
3985   "TARGET_FLOAT"
3986   "fcvtzs\\t%<GPI:w>0, %<GPF:s>1"
3987   [(set_attr "type" "f_cvtf2i")]
3990 (define_insn "fixuns_trunc<GPF:mode><GPI:mode>2"
3991   [(set (match_operand:GPI 0 "register_operand" "=r")
3992         (unsigned_fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
3993   "TARGET_FLOAT"
3994   "fcvtzu\\t%<GPI:w>0, %<GPF:s>1"
3995   [(set_attr "type" "f_cvtf2i")]
3998 (define_insn "<optab><fcvt_target><GPF:mode>2"
3999   [(set (match_operand:GPF 0 "register_operand" "=w,w")
4000         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))]
4001   ""
4002   "@
4003    <su_optab>cvtf\t%<GPF:s>0, %<s>1
4004    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
4005   [(set_attr "simd" "yes,no")
4006    (set_attr "fp" "no,yes")
4007    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
4010 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
4011   [(set (match_operand:GPF 0 "register_operand" "=w")
4012         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
4013   "TARGET_FLOAT"
4014   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
4015   [(set_attr "type" "f_cvti2f")]
4018 ;; -------------------------------------------------------------------
4019 ;; Floating-point arithmetic
4020 ;; -------------------------------------------------------------------
4022 (define_insn "add<mode>3"
4023   [(set (match_operand:GPF 0 "register_operand" "=w")
4024         (plus:GPF
4025          (match_operand:GPF 1 "register_operand" "w")
4026          (match_operand:GPF 2 "register_operand" "w")))]
4027   "TARGET_FLOAT"
4028   "fadd\\t%<s>0, %<s>1, %<s>2"
4029   [(set_attr "type" "fadd<s>")]
4032 (define_insn "sub<mode>3"
4033   [(set (match_operand:GPF 0 "register_operand" "=w")
4034         (minus:GPF
4035          (match_operand:GPF 1 "register_operand" "w")
4036          (match_operand:GPF 2 "register_operand" "w")))]
4037   "TARGET_FLOAT"
4038   "fsub\\t%<s>0, %<s>1, %<s>2"
4039   [(set_attr "type" "fadd<s>")]
4042 (define_insn "mul<mode>3"
4043   [(set (match_operand:GPF 0 "register_operand" "=w")
4044         (mult:GPF
4045          (match_operand:GPF 1 "register_operand" "w")
4046          (match_operand:GPF 2 "register_operand" "w")))]
4047   "TARGET_FLOAT"
4048   "fmul\\t%<s>0, %<s>1, %<s>2"
4049   [(set_attr "type" "fmul<s>")]
4052 (define_insn "*fnmul<mode>3"
4053   [(set (match_operand:GPF 0 "register_operand" "=w")
4054         (mult:GPF
4055                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
4056                  (match_operand:GPF 2 "register_operand" "w")))]
4057   "TARGET_FLOAT"
4058   "fnmul\\t%<s>0, %<s>1, %<s>2"
4059   [(set_attr "type" "fmul<s>")]
4062 (define_insn "div<mode>3"
4063   [(set (match_operand:GPF 0 "register_operand" "=w")
4064         (div:GPF
4065          (match_operand:GPF 1 "register_operand" "w")
4066          (match_operand:GPF 2 "register_operand" "w")))]
4067   "TARGET_FLOAT"
4068   "fdiv\\t%<s>0, %<s>1, %<s>2"
4069   [(set_attr "type" "fdiv<s>")]
4072 (define_insn "neg<mode>2"
4073   [(set (match_operand:GPF 0 "register_operand" "=w")
4074         (neg:GPF (match_operand:GPF 1 "register_operand" "w")))]
4075   "TARGET_FLOAT"
4076   "fneg\\t%<s>0, %<s>1"
4077   [(set_attr "type" "ffarith<s>")]
4080 (define_insn "sqrt<mode>2"
4081   [(set (match_operand:GPF 0 "register_operand" "=w")
4082         (sqrt:GPF (match_operand:GPF 1 "register_operand" "w")))]
4083   "TARGET_FLOAT"
4084   "fsqrt\\t%<s>0, %<s>1"
4085   [(set_attr "type" "fsqrt<s>")]
4088 (define_insn "abs<mode>2"
4089   [(set (match_operand:GPF 0 "register_operand" "=w")
4090         (abs:GPF (match_operand:GPF 1 "register_operand" "w")))]
4091   "TARGET_FLOAT"
4092   "fabs\\t%<s>0, %<s>1"
4093   [(set_attr "type" "ffarith<s>")]
4096 ;; Given that smax/smin do not specify the result when either input is NaN,
4097 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
4098 ;; for smin.
4100 (define_insn "smax<mode>3"
4101   [(set (match_operand:GPF 0 "register_operand" "=w")
4102         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
4103                   (match_operand:GPF 2 "register_operand" "w")))]
4104   "TARGET_FLOAT"
4105   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
4106   [(set_attr "type" "f_minmax<s>")]
4109 (define_insn "smin<mode>3"
4110   [(set (match_operand:GPF 0 "register_operand" "=w")
4111         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
4112                   (match_operand:GPF 2 "register_operand" "w")))]
4113   "TARGET_FLOAT"
4114   "fminnm\\t%<s>0, %<s>1, %<s>2"
4115   [(set_attr "type" "f_minmax<s>")]
4118 ;; -------------------------------------------------------------------
4119 ;; Reload support
4120 ;; -------------------------------------------------------------------
4122 (define_expand "aarch64_reload_mov<mode>"
4123   [(set (match_operand:TX 0 "register_operand" "=w")
4124         (match_operand:TX 1 "register_operand" "w"))
4125    (clobber (match_operand:DI 2 "register_operand" "=&r"))
4126   ]
4127   "TARGET_FLOAT"
4128   {
4129     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
4130     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
4131     gen_aarch64_movtilow_tilow (op0, op1);
4132     gen_aarch64_movdi_tihigh (operands[2], op1);
4133     gen_aarch64_movtihigh_di (op0, operands[2]);
4134     DONE;
4135   }
4138 ;; The following secondary reload helpers patterns are invoked
4139 ;; after or during reload as we don't want these patterns to start
4140 ;; kicking in during the combiner.
4142 (define_insn "aarch64_movdi_<mode>low"
4143   [(set (match_operand:DI 0 "register_operand" "=r")
4144         (truncate:DI (match_operand:TX 1 "register_operand" "w")))]
4145   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4146   "fmov\\t%x0, %d1"
4147   [(set_attr "type" "f_mrc")
4148    (set_attr "length" "4")
4149   ])
4151 (define_insn "aarch64_movdi_<mode>high"
4152   [(set (match_operand:DI 0 "register_operand" "=r")
4153         (truncate:DI
4154           (lshiftrt:TX (match_operand:TX 1 "register_operand" "w")
4155                        (const_int 64))))]
4156   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4157   "fmov\\t%x0, %1.d[1]"
4158   [(set_attr "type" "f_mrc")
4159    (set_attr "length" "4")
4160   ])
4162 (define_insn "aarch64_mov<mode>high_di"
4163   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
4164                          (const_int 64) (const_int 64))
4165         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
4166   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4167   "fmov\\t%0.d[1], %x1"
4168   [(set_attr "type" "f_mcr")
4169    (set_attr "length" "4")
4170   ])
4172 (define_insn "aarch64_mov<mode>low_di"
4173   [(set (match_operand:TX 0 "register_operand" "=w")
4174         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
4175   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4176   "fmov\\t%d0, %x1"
4177   [(set_attr "type" "f_mcr")
4178    (set_attr "length" "4")
4179   ])
4181 (define_insn "aarch64_movtilow_tilow"
4182   [(set (match_operand:TI 0 "register_operand" "=w")
4183         (zero_extend:TI
4184           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
4185   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
4186   "fmov\\t%d0, %d1"
4187   [(set_attr "type" "fmov")
4188    (set_attr "length" "4")
4189   ])
4191 ;; There is a deliberate reason why the parameters of high and lo_sum's
4192 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
4193 ;; and lo_sum's to be used with the labels defining the jump tables in
4194 ;; rodata section.
4196 (define_expand "add_losym"
4197   [(set (match_operand 0 "register_operand" "=r")
4198         (lo_sum (match_operand 1 "register_operand" "r")
4199                 (match_operand 2 "aarch64_valid_symref" "S")))]
4200   ""
4202   machine_mode mode = GET_MODE (operands[0]);
4204   emit_insn ((mode == DImode
4205               ? gen_add_losym_di
4206               : gen_add_losym_si) (operands[0],
4207                                    operands[1],
4208                                    operands[2]));
4209   DONE;
4212 (define_insn "add_losym_<mode>"
4213   [(set (match_operand:P 0 "register_operand" "=r")
4214         (lo_sum:P (match_operand:P 1 "register_operand" "r")
4215                   (match_operand 2 "aarch64_valid_symref" "S")))]
4216   ""
4217   "add\\t%<w>0, %<w>1, :lo12:%a2"
4218   [(set_attr "type" "alu_imm")]
4221 (define_insn "ldr_got_small_<mode>"
4222   [(set (match_operand:PTR 0 "register_operand" "=r")
4223         (unspec:PTR [(mem:PTR (lo_sum:PTR
4224                               (match_operand:PTR 1 "register_operand" "r")
4225                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
4226                     UNSPEC_GOTSMALLPIC))]
4227   ""
4228   "ldr\\t%<w>0, [%1, #:got_lo12:%a2]"
4229   [(set_attr "type" "load1")]
4232 (define_insn "ldr_got_small_sidi"
4233   [(set (match_operand:DI 0 "register_operand" "=r")
4234         (zero_extend:DI
4235          (unspec:SI [(mem:SI (lo_sum:DI
4236                              (match_operand:DI 1 "register_operand" "r")
4237                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
4238                     UNSPEC_GOTSMALLPIC)))]
4239   "TARGET_ILP32"
4240   "ldr\\t%w0, [%1, #:got_lo12:%a2]"
4241   [(set_attr "type" "load1")]
4244 (define_insn "ldr_got_tiny"
4245   [(set (match_operand:DI 0 "register_operand" "=r")
4246         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
4247                    UNSPEC_GOTTINYPIC))]
4248   ""
4249   "ldr\\t%0, %L1"
4250   [(set_attr "type" "load1")]
4253 (define_insn "aarch64_load_tp_hard"
4254   [(set (match_operand:DI 0 "register_operand" "=r")
4255         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
4256   ""
4257   "mrs\\t%0, tpidr_el0"
4258   [(set_attr "type" "mrs")]
4261 ;; The TLS ABI specifically requires that the compiler does not schedule
4262 ;; instructions in the TLS stubs, in order to enable linker relaxation.
4263 ;; Therefore we treat the stubs as an atomic sequence.
4264 (define_expand "tlsgd_small"
4265  [(parallel [(set (match_operand 0 "register_operand" "")
4266                   (call (mem:DI (match_dup 2)) (const_int 1)))
4267              (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
4268              (clobber (reg:DI LR_REGNUM))])]
4269  ""
4271   operands[2] = aarch64_tls_get_addr ();
4274 (define_insn "*tlsgd_small"
4275   [(set (match_operand 0 "register_operand" "")
4276         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
4277    (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
4278    (clobber (reg:DI LR_REGNUM))
4279   ]
4280   ""
4281   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
4282   [(set_attr "type" "call")
4283    (set_attr "length" "16")])
4285 (define_insn "tlsie_small_<mode>"
4286   [(set (match_operand:PTR 0 "register_operand" "=r")
4287         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
4288                    UNSPEC_GOTSMALLTLS))]
4289   ""
4290   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
4291   [(set_attr "type" "load1")
4292    (set_attr "length" "8")]
4295 (define_insn "tlsie_small_sidi"
4296   [(set (match_operand:DI 0 "register_operand" "=r")
4297         (zero_extend:DI
4298           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
4299                       UNSPEC_GOTSMALLTLS)))]
4300   ""
4301   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
4302   [(set_attr "type" "load1")
4303    (set_attr "length" "8")]
4306 (define_expand "tlsle_small"
4307   [(set (match_operand 0 "register_operand" "=r")
4308         (unspec [(match_operand 1 "register_operand" "r")
4309                    (match_operand 2 "aarch64_tls_le_symref" "S")]
4310                    UNSPEC_GOTSMALLTLS))]
4311   ""
4313   machine_mode mode = GET_MODE (operands[0]);
4314   emit_insn ((mode == DImode
4315               ? gen_tlsle_small_di
4316               : gen_tlsle_small_si) (operands[0],
4317                                      operands[1],
4318                                      operands[2]));
4319   DONE;
4322 (define_insn "tlsle_small_<mode>"
4323   [(set (match_operand:P 0 "register_operand" "=r")
4324         (unspec:P [(match_operand:P 1 "register_operand" "r")
4325                    (match_operand 2 "aarch64_tls_le_symref" "S")]
4326                    UNSPEC_GOTSMALLTLS))]
4327   ""
4328   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
4329   [(set_attr "type" "alu_sreg")
4330    (set_attr "length" "8")]
4333 (define_insn "tlsdesc_small_<mode>"
4334   [(set (reg:PTR R0_REGNUM)
4335         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
4336                    UNSPEC_TLSDESC))
4337    (clobber (reg:DI LR_REGNUM))
4338    (clobber (reg:CC CC_REGNUM))
4339    (clobber (match_scratch:DI 1 "=r"))]
4340   "TARGET_TLS_DESC"
4341   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
4342   [(set_attr "type" "call")
4343    (set_attr "length" "16")])
4345 (define_insn "stack_tie"
4346   [(set (mem:BLK (scratch))
4347         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
4348                      (match_operand:DI 1 "register_operand" "rk")]
4349                     UNSPEC_PRLG_STK))]
4350   ""
4351   ""
4352   [(set_attr "length" "0")]
4355 ;; Named pattern for expanding thread pointer reference.
4356 (define_expand "get_thread_pointerdi"
4357   [(match_operand:DI 0 "register_operand" "=r")]
4358   ""
4360   rtx tmp = aarch64_load_tp (operands[0]);
4361   if (tmp != operands[0])
4362     emit_move_insn (operands[0], tmp);
4363   DONE;
4366 ;; Named patterns for stack smashing protection.
4367 (define_expand "stack_protect_set"
4368   [(match_operand 0 "memory_operand")
4369    (match_operand 1 "memory_operand")]
4370   ""
4372   machine_mode mode = GET_MODE (operands[0]);
4374   emit_insn ((mode == DImode
4375               ? gen_stack_protect_set_di
4376               : gen_stack_protect_set_si) (operands[0], operands[1]));
4377   DONE;
4380 (define_insn "stack_protect_set_<mode>"
4381   [(set (match_operand:PTR 0 "memory_operand" "=m")
4382         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
4383          UNSPEC_SP_SET))
4384    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
4385   ""
4386   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
4387   [(set_attr "length" "12")
4388    (set_attr "type" "multiple")])
4390 (define_expand "stack_protect_test"
4391   [(match_operand 0 "memory_operand")
4392    (match_operand 1 "memory_operand")
4393    (match_operand 2)]
4394   ""
4396   rtx result;
4397   machine_mode mode = GET_MODE (operands[0]);
4399   result = gen_reg_rtx(mode);
4401   emit_insn ((mode == DImode
4402               ? gen_stack_protect_test_di
4403               : gen_stack_protect_test_si) (result,
4404                                             operands[0],
4405                                             operands[1]));
4407   if (mode == DImode)
4408     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
4409                                     result, const0_rtx, operands[2]));
4410   else
4411     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
4412                                     result, const0_rtx, operands[2]));
4413   DONE;
4416 (define_insn "stack_protect_test_<mode>"
4417   [(set (match_operand:PTR 0 "register_operand" "=r")
4418         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
4419                      (match_operand:PTR 2 "memory_operand" "m")]
4420          UNSPEC_SP_TEST))
4421    (clobber (match_scratch:PTR 3 "=&r"))]
4422   ""
4423   "ldr\t%<w>3, %x1\;ldr\t%<w>0, %x2\;eor\t%<w>0, %<w>3, %<w>0"
4424   [(set_attr "length" "12")
4425    (set_attr "type" "multiple")])
4427 ;; Write Floating-point Control Register.
4428 (define_insn "set_fpcr"
4429   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
4430   ""
4431   "msr\\tfpcr, %0"
4432   [(set_attr "type" "mrs")])
4434 ;; Read Floating-point Control Register.
4435 (define_insn "get_fpcr"
4436   [(set (match_operand:SI 0 "register_operand" "=r")
4437         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
4438   ""
4439   "mrs\\t%0, fpcr"
4440   [(set_attr "type" "mrs")])
4442 ;; Write Floating-point Status Register.
4443 (define_insn "set_fpsr"
4444   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
4445   ""
4446   "msr\\tfpsr, %0"
4447   [(set_attr "type" "mrs")])
4449 ;; Read Floating-point Status Register.
4450 (define_insn "get_fpsr"
4451   [(set (match_operand:SI 0 "register_operand" "=r")
4452         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
4453   ""
4454   "mrs\\t%0, fpsr"
4455   [(set_attr "type" "mrs")])
4458 ;; Define the subtract-one-and-jump insns so loop.c
4459 ;; knows what to generate.
4460 (define_expand "doloop_end"
4461   [(use (match_operand 0 "" ""))      ; loop pseudo
4462    (use (match_operand 1 "" ""))]     ; label
4463   "optimize > 0 && flag_modulo_sched"
4465   rtx s0;
4466   rtx bcomp;
4467   rtx loc_ref;
4468   rtx cc_reg;
4469   rtx insn;
4470   rtx cmp;
4472   /* Currently SMS relies on the do-loop pattern to recognize loops
4473      where (1) the control part consists of all insns defining and/or
4474      using a certain 'count' register and (2) the loop count can be
4475      adjusted by modifying this register prior to the loop.
4476      ??? The possible introduction of a new block to initialize the
4477      new IV can potentially affect branch optimizations.  */
4479   if (GET_MODE (operands[0]) != DImode)
4480     FAIL;
4482   s0 = operands [0];
4483   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
4485   cmp = XVECEXP (PATTERN (insn), 0, 0);
4486   cc_reg = SET_DEST (cmp);
4487   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
4488   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
4489   emit_jump_insn (gen_rtx_SET (pc_rtx,
4490                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
4491                                                      loc_ref, pc_rtx)));
4492   DONE;
4495 ;; AdvSIMD Stuff
4496 (include "aarch64-simd.md")
4498 ;; Atomic Operations
4499 (include "atomics.md")
4501 ;; ldp/stp peephole patterns
4502 (include "aarch64-ldpstp.md")