[AArch64] Merge stores of D-register values with different modes
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blob8a894f8ac00f0fc76cc9f1fc9f0c17b429482db8
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2018 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     (V4_REGNUM          36)
61     (V8_REGNUM          40)
62     (V12_REGNUM         44)
63     (V15_REGNUM         47)
64     (V16_REGNUM         48)
65     (V20_REGNUM         52)
66     (V24_REGNUM         56)
67     (V28_REGNUM         60)
68     (V31_REGNUM         63)
69     (LAST_SAVED_REGNUM  63)
70     (SFP_REGNUM         64)
71     (AP_REGNUM          65)
72     (CC_REGNUM          66)
73     ;; Defined only to make the DWARF description simpler.
74     (VG_REGNUM          67)
75     (P0_REGNUM          68)
76     (P1_REGNUM          69)
77     (P2_REGNUM          70)
78     (P3_REGNUM          71)
79     (P4_REGNUM          72)
80     (P5_REGNUM          73)
81     (P6_REGNUM          74)
82     (P7_REGNUM          75)
83     (P8_REGNUM          76)
84     (P9_REGNUM          77)
85     (P10_REGNUM         78)
86     (P11_REGNUM         79)
87     (P12_REGNUM         80)
88     (P13_REGNUM         81)
89     (P14_REGNUM         82)
90     (P15_REGNUM         83)
91   ]
94 (define_c_enum "unspec" [
95     UNSPEC_AUTI1716
96     UNSPEC_AUTISP
97     UNSPEC_CASESI
98     UNSPEC_CRC32B
99     UNSPEC_CRC32CB
100     UNSPEC_CRC32CH
101     UNSPEC_CRC32CW
102     UNSPEC_CRC32CX
103     UNSPEC_CRC32H
104     UNSPEC_CRC32W
105     UNSPEC_CRC32X
106     UNSPEC_FCVTZS
107     UNSPEC_FCVTZU
108     UNSPEC_URECPE
109     UNSPEC_FRECPE
110     UNSPEC_FRECPS
111     UNSPEC_FRECPX
112     UNSPEC_FRINTA
113     UNSPEC_FRINTI
114     UNSPEC_FRINTM
115     UNSPEC_FRINTN
116     UNSPEC_FRINTP
117     UNSPEC_FRINTX
118     UNSPEC_FRINTZ
119     UNSPEC_GOTSMALLPIC
120     UNSPEC_GOTSMALLPIC28K
121     UNSPEC_GOTSMALLTLS
122     UNSPEC_GOTTINYPIC
123     UNSPEC_GOTTINYTLS
124     UNSPEC_LD1
125     UNSPEC_LD2
126     UNSPEC_LD2_DREG
127     UNSPEC_LD2_DUP
128     UNSPEC_LD3
129     UNSPEC_LD3_DREG
130     UNSPEC_LD3_DUP
131     UNSPEC_LD4
132     UNSPEC_LD4_DREG
133     UNSPEC_LD4_DUP
134     UNSPEC_LD2_LANE
135     UNSPEC_LD3_LANE
136     UNSPEC_LD4_LANE
137     UNSPEC_MB
138     UNSPEC_NOP
139     UNSPEC_PACI1716
140     UNSPEC_PACISP
141     UNSPEC_PRLG_STK
142     UNSPEC_REV
143     UNSPEC_RBIT
144     UNSPEC_SABAL
145     UNSPEC_SABDL2
146     UNSPEC_SADALP
147     UNSPEC_SCVTF
148     UNSPEC_SISD_NEG
149     UNSPEC_SISD_SSHL
150     UNSPEC_SISD_USHL
151     UNSPEC_SSHL_2S
152     UNSPEC_ST1
153     UNSPEC_ST2
154     UNSPEC_ST3
155     UNSPEC_ST4
156     UNSPEC_ST2_LANE
157     UNSPEC_ST3_LANE
158     UNSPEC_ST4_LANE
159     UNSPEC_TLS
160     UNSPEC_TLSDESC
161     UNSPEC_TLSLE12
162     UNSPEC_TLSLE24
163     UNSPEC_TLSLE32
164     UNSPEC_TLSLE48
165     UNSPEC_UABAL
166     UNSPEC_UABDL2
167     UNSPEC_UADALP
168     UNSPEC_UCVTF
169     UNSPEC_USHL_2S
170     UNSPEC_VSTRUCTDUMMY
171     UNSPEC_SP_SET
172     UNSPEC_SP_TEST
173     UNSPEC_RSQRT
174     UNSPEC_RSQRTE
175     UNSPEC_RSQRTS
176     UNSPEC_NZCV
177     UNSPEC_XPACLRI
178     UNSPEC_LD1_SVE
179     UNSPEC_ST1_SVE
180     UNSPEC_LD1RQ
181     UNSPEC_LD1_GATHER
182     UNSPEC_ST1_SCATTER
183     UNSPEC_MERGE_PTRUE
184     UNSPEC_PTEST_PTRUE
185     UNSPEC_UNPACKSHI
186     UNSPEC_UNPACKUHI
187     UNSPEC_UNPACKSLO
188     UNSPEC_UNPACKULO
189     UNSPEC_PACK
190     UNSPEC_FLOAT_CONVERT
191     UNSPEC_WHILE_LO
192     UNSPEC_LDN
193     UNSPEC_STN
194     UNSPEC_INSR
195     UNSPEC_CLASTB
196     UNSPEC_FADDA
197     UNSPEC_REV_SUBREG
200 (define_c_enum "unspecv" [
201     UNSPECV_EH_RETURN           ; Represent EH_RETURN
202     UNSPECV_GET_FPCR            ; Represent fetch of FPCR content.
203     UNSPECV_SET_FPCR            ; Represent assign of FPCR content.
204     UNSPECV_GET_FPSR            ; Represent fetch of FPSR content.
205     UNSPECV_SET_FPSR            ; Represent assign of FPSR content.
206     UNSPECV_BLOCKAGE            ; Represent a blockage
207     UNSPECV_PROBE_STACK_RANGE   ; Represent stack range probing.
208   ]
211 ;; If further include files are added the defintion of MD_INCLUDES
212 ;; must be updated.
214 (include "constraints.md")
215 (include "predicates.md")
216 (include "iterators.md")
218 ;; -------------------------------------------------------------------
219 ;; Instruction types and attributes
220 ;; -------------------------------------------------------------------
222 ; The "type" attribute is included here from AArch32 backend to be able
223 ; to share pipeline descriptions.
224 (include "../arm/types.md")
226 ;; It is important to set the fp or simd attributes to yes when a pattern
227 ;; alternative uses the FP or SIMD register files, usually signified by use of
228 ;; the 'w' constraint.  This will ensure that the alternative will be
229 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
230 ;; architecture extensions.  If all the alternatives in a pattern use the
231 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
232 ;; or TARGET_SIMD.
234 ;; Attribute that specifies whether or not the instruction touches fp
235 ;; registers.  When this is set to yes for an alternative, that alternative
236 ;; will be disabled when !TARGET_FLOAT.
237 (define_attr "fp" "no,yes" (const_string "no"))
239 ;; Attribute that specifies whether or not the instruction touches half
240 ;; precision fp registers.  When this is set to yes for an alternative,
241 ;; that alternative will be disabled when !TARGET_FP_F16INST.
242 (define_attr "fp16" "no,yes" (const_string "no"))
244 ;; Attribute that specifies whether or not the instruction touches simd
245 ;; registers.  When this is set to yes for an alternative, that alternative
246 ;; will be disabled when !TARGET_SIMD.
247 (define_attr "simd" "no,yes" (const_string "no"))
249 ;; Attribute that specifies whether or not the instruction uses SVE.
250 ;; When this is set to yes for an alternative, that alternative
251 ;; will be disabled when !TARGET_SVE.
252 (define_attr "sve" "no,yes" (const_string "no"))
254 (define_attr "length" ""
255   (const_int 4))
257 ;; Attribute that controls whether an alternative is enabled or not.
258 ;; Currently it is only used to disable alternatives which touch fp or simd
259 ;; registers when -mgeneral-regs-only is specified.
260 (define_attr "enabled" "no,yes"
261   (cond [(ior
262             (and (eq_attr "fp" "yes")
263                  (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
264             (and (eq_attr "simd" "yes")
265                  (eq (symbol_ref "TARGET_SIMD") (const_int 0)))
266             (and (eq_attr "fp16" "yes")
267                  (eq (symbol_ref "TARGET_FP_F16INST") (const_int 0)))
268             (and (eq_attr "sve" "yes")
269                  (eq (symbol_ref "TARGET_SVE") (const_int 0))))
270             (const_string "no")
271         ] (const_string "yes")))
273 ;; Attribute that specifies whether we are dealing with a branch to a
274 ;; label that is far away, i.e. further away than the maximum/minimum
275 ;; representable in a signed 21-bits number.
276 ;; 0 :=: no
277 ;; 1 :=: yes
278 (define_attr "far_branch" "" (const_int 0))
280 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
281 ;; no predicated insns.
282 (define_attr "predicated" "yes,no" (const_string "no"))
284 ;; -------------------------------------------------------------------
285 ;; Pipeline descriptions and scheduling
286 ;; -------------------------------------------------------------------
288 ;; Processor types.
289 (include "aarch64-tune.md")
291 ;; Scheduling
292 (include "../arm/cortex-a53.md")
293 (include "../arm/cortex-a57.md")
294 (include "../arm/exynos-m1.md")
295 (include "falkor.md")
296 (include "thunderx.md")
297 (include "../arm/xgene1.md")
298 (include "thunderx2t99.md")
300 ;; -------------------------------------------------------------------
301 ;; Jumps and other miscellaneous insns
302 ;; -------------------------------------------------------------------
304 (define_insn "indirect_jump"
305   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
306   ""
307   "br\\t%0"
308   [(set_attr "type" "branch")]
311 (define_insn "jump"
312   [(set (pc) (label_ref (match_operand 0 "" "")))]
313   ""
314   "b\\t%l0"
315   [(set_attr "type" "branch")]
318 (define_expand "cbranch<mode>4"
319   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
320                             [(match_operand:GPI 1 "register_operand" "")
321                              (match_operand:GPI 2 "aarch64_plus_operand" "")])
322                            (label_ref (match_operand 3 "" ""))
323                            (pc)))]
324   ""
325   "
326   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
327                                          operands[2]);
328   operands[2] = const0_rtx;
329   "
332 (define_expand "cbranch<mode>4"
333   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
334                             [(match_operand:GPF 1 "register_operand" "")
335                              (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
336                            (label_ref (match_operand 3 "" ""))
337                            (pc)))]
338   ""
339   "
340   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
341                                          operands[2]);
342   operands[2] = const0_rtx;
343   "
346 (define_expand "cbranchcc4"
347   [(set (pc) (if_then_else
348               (match_operator 0 "aarch64_comparison_operator"
349                [(match_operand 1 "cc_register" "")
350                 (match_operand 2 "const0_operand")])
351               (label_ref (match_operand 3 "" ""))
352               (pc)))]
353   ""
354   "")
356 (define_insn "ccmp<mode>"
357   [(set (match_operand:CC 1 "cc_register" "")
358         (if_then_else:CC
359           (match_operator 4 "aarch64_comparison_operator"
360            [(match_operand 0 "cc_register" "")
361             (const_int 0)])
362           (compare:CC
363             (match_operand:GPI 2 "register_operand" "r,r,r")
364             (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
365           (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
366   ""
367   "@
368    ccmp\\t%<w>2, %<w>3, %k5, %m4
369    ccmp\\t%<w>2, %3, %k5, %m4
370    ccmn\\t%<w>2, #%n3, %k5, %m4"
371   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
374 (define_insn "fccmp<mode>"
375   [(set (match_operand:CCFP 1 "cc_register" "")
376         (if_then_else:CCFP
377           (match_operator 4 "aarch64_comparison_operator"
378            [(match_operand 0 "cc_register" "")
379             (const_int 0)])
380           (compare:CCFP
381             (match_operand:GPF 2 "register_operand" "w")
382             (match_operand:GPF 3 "register_operand" "w"))
383           (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
384   "TARGET_FLOAT"
385   "fccmp\\t%<s>2, %<s>3, %k5, %m4"
386   [(set_attr "type" "fccmp<s>")]
389 (define_insn "fccmpe<mode>"
390   [(set (match_operand:CCFPE 1 "cc_register" "")
391          (if_then_else:CCFPE
392           (match_operator 4 "aarch64_comparison_operator"
393            [(match_operand 0 "cc_register" "")
394           (const_int 0)])
395            (compare:CCFPE
396             (match_operand:GPF 2 "register_operand" "w")
397             (match_operand:GPF 3 "register_operand" "w"))
398           (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
399   "TARGET_FLOAT"
400   "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
401   [(set_attr "type" "fccmp<s>")]
404 ;; Expansion of signed mod by a power of 2 using CSNEG.
405 ;; For x0 % n where n is a power of 2 produce:
406 ;; negs   x1, x0
407 ;; and    x0, x0, #(n - 1)
408 ;; and    x1, x1, #(n - 1)
409 ;; csneg  x0, x0, x1, mi
411 (define_expand "mod<mode>3"
412   [(match_operand:GPI 0 "register_operand" "")
413    (match_operand:GPI 1 "register_operand" "")
414    (match_operand:GPI 2 "const_int_operand" "")]
415   ""
416   {
417     HOST_WIDE_INT val = INTVAL (operands[2]);
419     if (val <= 0
420        || exact_log2 (val) <= 0
421        || !aarch64_bitmask_imm (val - 1, <MODE>mode))
422       FAIL;
424     rtx mask = GEN_INT (val - 1);
426     /* In the special case of x0 % 2 we can do the even shorter:
427         cmp    x0, xzr
428         and    x0, x0, 1
429         cneg   x0, x0, lt.  */
430     if (val == 2)
431       {
432         rtx masked = gen_reg_rtx (<MODE>mode);
433         rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
434         emit_insn (gen_and<mode>3 (masked, operands[1], mask));
435         rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
436         emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
437         DONE;
438       }
440     rtx neg_op = gen_reg_rtx (<MODE>mode);
441     rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
443     /* Extract the condition register and mode.  */
444     rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
445     rtx cc_reg = SET_DEST (cmp);
446     rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
448     rtx masked_pos = gen_reg_rtx (<MODE>mode);
449     emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
451     rtx masked_neg = gen_reg_rtx (<MODE>mode);
452     emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
454     emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
455                                        masked_neg, masked_pos));
456     DONE;
457   }
460 (define_insn "condjump"
461   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
462                             [(match_operand 1 "cc_register" "") (const_int 0)])
463                            (label_ref (match_operand 2 "" ""))
464                            (pc)))]
465   ""
466   {
467     if (get_attr_length (insn) == 8)
468       return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
469     else
470       return  "b%m0\\t%l2";
471   }
472   [(set_attr "type" "branch")
473    (set (attr "length")
474         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
475                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
476                       (const_int 4)
477                       (const_int 8)))
478    (set (attr "far_branch")
479         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
480                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
481                       (const_int 0)
482                       (const_int 1)))]
485 ;; For a 24-bit immediate CST we can optimize the compare for equality
486 ;; and branch sequence from:
487 ;;      mov     x0, #imm1
488 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
489 ;;      cmp     x1, x0
490 ;;      b<ne,eq> .Label
491 ;; into the shorter:
492 ;;      sub     x0, x1, #(CST & 0xfff000)
493 ;;      subs    x0, x0, #(CST & 0x000fff)
494 ;;      b<ne,eq> .Label
495 (define_insn_and_split "*compare_condjump<mode>"
496   [(set (pc) (if_then_else (EQL
497                               (match_operand:GPI 0 "register_operand" "r")
498                               (match_operand:GPI 1 "aarch64_imm24" "n"))
499                            (label_ref:P (match_operand 2 "" ""))
500                            (pc)))]
501   "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
502    && !aarch64_plus_operand (operands[1], <MODE>mode)
503    && !reload_completed"
504   "#"
505   "&& true"
506   [(const_int 0)]
507   {
508     HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
509     HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
510     rtx tmp = gen_reg_rtx (<MODE>mode);
511     emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
512     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
513     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
514     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
515     emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
516     DONE;
517   }
520 (define_expand "casesi"
521   [(match_operand:SI 0 "register_operand" "")   ; Index
522    (match_operand:SI 1 "const_int_operand" "")  ; Lower bound
523    (match_operand:SI 2 "const_int_operand" "")  ; Total range
524    (match_operand:DI 3 "" "")                   ; Table label
525    (match_operand:DI 4 "" "")]                  ; Out of range label
526   ""
527   {
528     if (operands[1] != const0_rtx)
529       {
530         rtx reg = gen_reg_rtx (SImode);
532         /* Canonical RTL says that if you have:
534            (minus (X) (CONST))
536            then this should be emitted as:
538            (plus (X) (-CONST))
540            The use of trunc_int_for_mode ensures that the resulting
541            constant can be represented in SImode, this is important
542            for the corner case where operand[1] is INT_MIN.  */
544         operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
546         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
547               (operands[1], SImode))
548           operands[1] = force_reg (SImode, operands[1]);
549         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
550         operands[0] = reg;
551       }
553     if (!aarch64_plus_operand (operands[2], SImode))
554       operands[2] = force_reg (SImode, operands[2]);
555     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
556                                                  const0_rtx),
557                                     operands[0], operands[2], operands[4]));
559     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3]));
560     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
561                                          operands[3]));
562     DONE;
563   }
566 (define_insn "casesi_dispatch"
567   [(parallel
568     [(set (pc)
569           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
570                            (match_operand:SI 1 "register_operand" "r")]
571                         UNSPEC_CASESI)))
572      (clobber (reg:CC CC_REGNUM))
573      (clobber (match_scratch:DI 3 "=r"))
574      (clobber (match_scratch:DI 4 "=r"))
575      (use (label_ref (match_operand 2 "" "")))])]
576   ""
577   "*
578   return aarch64_output_casesi (operands);
579   "
580   [(set_attr "length" "16")
581    (set_attr "type" "branch")]
584 (define_insn "nop"
585   [(unspec[(const_int 0)] UNSPEC_NOP)]
586   ""
587   "nop"
588   [(set_attr "type" "no_insn")]
591 (define_insn "prefetch"
592   [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
593             (match_operand:QI 1 "const_int_operand" "")
594             (match_operand:QI 2 "const_int_operand" ""))]
595   ""
596   {
597     const char * pftype[2][4] =
598     {
599       {"prfm\\tPLDL1STRM, %0",
600        "prfm\\tPLDL3KEEP, %0",
601        "prfm\\tPLDL2KEEP, %0",
602        "prfm\\tPLDL1KEEP, %0"},
603       {"prfm\\tPSTL1STRM, %0",
604        "prfm\\tPSTL3KEEP, %0",
605        "prfm\\tPSTL2KEEP, %0",
606        "prfm\\tPSTL1KEEP, %0"},
607     };
609     int locality = INTVAL (operands[2]);
611     gcc_assert (IN_RANGE (locality, 0, 3));
613     /* PRFM accepts the same addresses as a 64-bit LDR so wrap
614        the address into a DImode MEM so that aarch64_print_operand knows
615        how to print it.  */
616     operands[0] = gen_rtx_MEM (DImode, operands[0]);
617     return pftype[INTVAL(operands[1])][locality];
618   }
619   [(set_attr "type" "load_4")]
622 (define_insn "trap"
623   [(trap_if (const_int 1) (const_int 8))]
624   ""
625   "brk #1000"
626   [(set_attr "type" "trap")])
628 (define_expand "prologue"
629   [(clobber (const_int 0))]
630   ""
631   "
632   aarch64_expand_prologue ();
633   DONE;
634   "
637 (define_expand "epilogue"
638   [(clobber (const_int 0))]
639   ""
640   "
641   aarch64_expand_epilogue (false);
642   DONE;
643   "
646 (define_expand "sibcall_epilogue"
647   [(clobber (const_int 0))]
648   ""
649   "
650   aarch64_expand_epilogue (true);
651   DONE;
652   "
655 (define_insn "*do_return"
656   [(return)]
657   ""
658   {
659     if (aarch64_return_address_signing_enabled ()
660         && TARGET_ARMV8_3
661         && !crtl->calls_eh_return)
662       return "retaa";
664     return "ret";
665   }
666   [(set_attr "type" "branch")]
669 (define_expand "return"
670   [(simple_return)]
671   "aarch64_use_return_insn_p ()"
672   ""
675 (define_insn "simple_return"
676   [(simple_return)]
677   ""
678   "ret"
679   [(set_attr "type" "branch")]
682 (define_insn "*cb<optab><mode>1"
683   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
684                                 (const_int 0))
685                            (label_ref (match_operand 1 "" ""))
686                            (pc)))]
687   ""
688   {
689     if (get_attr_length (insn) == 8)
690       return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
691     else
692       return "<cbz>\\t%<w>0, %l1";
693   }
694   [(set_attr "type" "branch")
695    (set (attr "length")
696         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
697                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
698                       (const_int 4)
699                       (const_int 8)))
700    (set (attr "far_branch")
701         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
702                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
703                       (const_int 0)
704                       (const_int 1)))]
707 (define_insn "*tb<optab><mode>1"
708   [(set (pc) (if_then_else
709               (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
710                                     (const_int 1)
711                                     (match_operand 1
712                                       "aarch64_simd_shift_imm_<mode>" "n"))
713                    (const_int 0))
714              (label_ref (match_operand 2 "" ""))
715              (pc)))
716    (clobber (reg:CC CC_REGNUM))]
717   ""
718   {
719     if (get_attr_length (insn) == 8)
720       {
721         if (get_attr_far_branch (insn) == 1)
722           return aarch64_gen_far_branch (operands, 2, "Ltb",
723                                          "<inv_tb>\\t%<w>0, %1, ");
724         else
725           {
726             operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
727             return "tst\t%<w>0, %1\;<bcond>\t%l2";
728           }
729       }
730     else
731       return "<tbz>\t%<w>0, %1, %l2";
732   }
733   [(set_attr "type" "branch")
734    (set (attr "length")
735         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
736                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
737                       (const_int 4)
738                       (const_int 8)))
739    (set (attr "far_branch")
740         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
741                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
742                       (const_int 0)
743                       (const_int 1)))]
747 (define_insn "*cb<optab><mode>1"
748   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
749                                  (const_int 0))
750                            (label_ref (match_operand 1 "" ""))
751                            (pc)))
752    (clobber (reg:CC CC_REGNUM))]
753   ""
754   {
755     if (get_attr_length (insn) == 8)
756       {
757         if (get_attr_far_branch (insn) == 1)
758           return aarch64_gen_far_branch (operands, 1, "Ltb",
759                                          "<inv_tb>\\t%<w>0, <sizem1>, ");
760         else
761           {
762             char buf[64];
763             uint64_t val = ((uint64_t) 1)
764                 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
765             sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
766             output_asm_insn (buf, operands);
767             return "<bcond>\t%l1";
768           }
769       }
770     else
771       return "<tbz>\t%<w>0, <sizem1>, %l1";
772   }
773   [(set_attr "type" "branch")
774    (set (attr "length")
775         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
776                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
777                       (const_int 4)
778                       (const_int 8)))
779    (set (attr "far_branch")
780         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
781                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
782                       (const_int 0)
783                       (const_int 1)))]
786 ;; -------------------------------------------------------------------
787 ;; Subroutine calls and sibcalls
788 ;; -------------------------------------------------------------------
790 (define_expand "call"
791   [(parallel [(call (match_operand 0 "memory_operand" "")
792                     (match_operand 1 "general_operand" ""))
793               (use (match_operand 2 "" ""))
794               (clobber (reg:DI LR_REGNUM))])]
795   ""
796   "
797   {
798     aarch64_expand_call (NULL_RTX, operands[0], false);
799     DONE;
800   }"
803 (define_insn "*call_insn"
804   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
805          (match_operand 1 "" ""))
806    (clobber (reg:DI LR_REGNUM))]
807   ""
808   "@
809   blr\\t%0
810   bl\\t%c0"
811   [(set_attr "type" "call, call")]
814 (define_expand "call_value"
815   [(parallel [(set (match_operand 0 "" "")
816                    (call (match_operand 1 "memory_operand" "")
817                          (match_operand 2 "general_operand" "")))
818               (use (match_operand 3 "" ""))
819               (clobber (reg:DI LR_REGNUM))])]
820   ""
821   "
822   {
823     aarch64_expand_call (operands[0], operands[1], false);
824     DONE;
825   }"
828 (define_insn "*call_value_insn"
829   [(set (match_operand 0 "" "")
830         (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
831                       (match_operand 2 "" "")))
832    (clobber (reg:DI LR_REGNUM))]
833   ""
834   "@
835   blr\\t%1
836   bl\\t%c1"
837   [(set_attr "type" "call, call")]
840 (define_expand "sibcall"
841   [(parallel [(call (match_operand 0 "memory_operand" "")
842                     (match_operand 1 "general_operand" ""))
843               (return)
844               (use (match_operand 2 "" ""))])]
845   ""
846   {
847     aarch64_expand_call (NULL_RTX, operands[0], true);
848     DONE;
849   }
852 (define_expand "sibcall_value"
853   [(parallel [(set (match_operand 0 "" "")
854                    (call (match_operand 1 "memory_operand" "")
855                          (match_operand 2 "general_operand" "")))
856               (return)
857               (use (match_operand 3 "" ""))])]
858   ""
859   {
860     aarch64_expand_call (operands[0], operands[1], true);
861     DONE;
862   }
865 (define_insn "*sibcall_insn"
866   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
867          (match_operand 1 "" ""))
868    (return)]
869   "SIBLING_CALL_P (insn)"
870   "@
871    br\\t%0
872    b\\t%c0"
873   [(set_attr "type" "branch, branch")]
876 (define_insn "*sibcall_value_insn"
877   [(set (match_operand 0 "" "")
878         (call (mem:DI
879                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
880               (match_operand 2 "" "")))
881    (return)]
882   "SIBLING_CALL_P (insn)"
883   "@
884    br\\t%1
885    b\\t%c1"
886   [(set_attr "type" "branch, branch")]
889 ;; Call subroutine returning any type.
891 (define_expand "untyped_call"
892   [(parallel [(call (match_operand 0 "")
893                     (const_int 0))
894               (match_operand 1 "")
895               (match_operand 2 "")])]
896   ""
898   int i;
900   emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
902   for (i = 0; i < XVECLEN (operands[2], 0); i++)
903     {
904       rtx set = XVECEXP (operands[2], 0, i);
905       emit_move_insn (SET_DEST (set), SET_SRC (set));
906     }
908   /* The optimizer does not know that the call sets the function value
909      registers we stored in the result block.  We avoid problems by
910      claiming that all hard registers are used and clobbered at this
911      point.  */
912   emit_insn (gen_blockage ());
913   DONE;
916 ;; -------------------------------------------------------------------
917 ;; Moves
918 ;; -------------------------------------------------------------------
920 (define_expand "mov<mode>"
921   [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
922         (match_operand:SHORT 1 "general_operand" ""))]
923   ""
924   "
925     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
926       operands[1] = force_reg (<MODE>mode, operands[1]);
928     if (GET_CODE (operands[1]) == CONST_POLY_INT)
929       {
930         aarch64_expand_mov_immediate (operands[0], operands[1]);
931         DONE;
932       }
933   "
936 (define_insn "*mov<mode>_aarch64"
937   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,    w,r  ,r,w, m,m,r,w,w")
938         (match_operand:SHORT 1 "aarch64_mov_operand"  " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
939   "(register_operand (operands[0], <MODE>mode)
940     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
942    switch (which_alternative)
943      {
944      case 0:
945        return "mov\t%w0, %w1";
946      case 1:
947        return "mov\t%w0, %1";
948      case 2:
949        return aarch64_output_scalar_simd_mov_immediate (operands[1],
950                                                         <MODE>mode);
951      case 3:
952        return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
953      case 4:
954        return "ldr<size>\t%w0, %1";
955      case 5:
956        return "ldr\t%<size>0, %1";
957      case 6:
958        return "str<size>\t%w1, %0";
959      case 7:
960        return "str\t%<size>1, %0";
961      case 8:
962        return "umov\t%w0, %1.<v>[0]";
963      case 9:
964        return "dup\t%0.<Vallxd>, %w1";
965      case 10:
966        return "dup\t%<Vetype>0, %1.<v>[0]";
967      default:
968        gcc_unreachable ();
969      }
971   ;; The "mov_imm" type for CNT is just a placeholder.
972   [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
973                      store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
974    (set_attr "simd" "*,*,yes,*,*,*,*,*,yes,yes,yes")
975    (set_attr "sve" "*,*,*,yes,*,*,*,*,*,*,*")]
978 (define_expand "mov<mode>"
979   [(set (match_operand:GPI 0 "nonimmediate_operand" "")
980         (match_operand:GPI 1 "general_operand" ""))]
981   ""
982   "
983     if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
984         && <MODE>mode == DImode
985         && aarch64_split_dimode_const_store (operands[0], operands[1]))
986       DONE;
988     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
989       operands[1] = force_reg (<MODE>mode, operands[1]);
991     /* FIXME: RR we still need to fix up what we are doing with
992        symbol_refs and other types of constants.  */
993     if (CONSTANT_P (operands[1])
994         && !CONST_INT_P (operands[1]))
995      {
996        aarch64_expand_mov_immediate (operands[0], operands[1]);
997        DONE;
998      }
999   "
1002 (define_insn_and_split "*movsi_aarch64"
1003   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m,  r,  r, w,r,w, w")
1004         (match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1005   "(register_operand (operands[0], SImode)
1006     || aarch64_reg_or_zero (operands[1], SImode))"
1007   "@
1008    mov\\t%w0, %w1
1009    mov\\t%w0, %w1
1010    mov\\t%w0, %w1
1011    mov\\t%w0, %1
1012    #
1013    * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1014    ldr\\t%w0, %1
1015    ldr\\t%s0, %1
1016    str\\t%w1, %0
1017    str\\t%s1, %0
1018    adr\\t%x0, %c1
1019    adrp\\t%x0, %A1
1020    fmov\\t%s0, %w1
1021    fmov\\t%w0, %s1
1022    fmov\\t%s0, %s1
1023    * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
1024   "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1025     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1026    [(const_int 0)]
1027    "{
1028        aarch64_expand_mov_immediate (operands[0], operands[1]);
1029        DONE;
1030     }"
1031   ;; The "mov_imm" type for CNT is just a placeholder.
1032   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1033                     load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1034    (set_attr "fp" "*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1035    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
1036    (set_attr "sve" "*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
1039 (define_insn_and_split "*movdi_aarch64"
1040   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m,  r,  r, w,r,w, w")
1041         (match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1042   "(register_operand (operands[0], DImode)
1043     || aarch64_reg_or_zero (operands[1], DImode))"
1044   "@
1045    mov\\t%x0, %x1
1046    mov\\t%0, %x1
1047    mov\\t%x0, %1
1048    mov\\t%x0, %1
1049    mov\\t%w0, %1
1050    #
1051    * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1052    ldr\\t%x0, %1
1053    ldr\\t%d0, %1
1054    str\\t%x1, %0
1055    str\\t%d1, %0
1056    adr\\t%x0, %c1
1057    adrp\\t%x0, %A1
1058    fmov\\t%d0, %x1
1059    fmov\\t%x0, %d1
1060    fmov\\t%d0, %d1
1061    * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
1062    "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1063     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1064    [(const_int 0)]
1065    "{
1066        aarch64_expand_mov_immediate (operands[0], operands[1]);
1067        DONE;
1068     }"
1069   ;; The "mov_imm" type for CNTD is just a placeholder.
1070   [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1071                      load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1072                      neon_move")
1073    (set_attr "fp" "*,*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1074    (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
1075    (set_attr "sve" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
1078 (define_insn "insv_imm<mode>"
1079   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1080                           (const_int 16)
1081                           (match_operand:GPI 1 "const_int_operand" "n"))
1082         (match_operand:GPI 2 "const_int_operand" "n"))]
1083   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1084    && UINTVAL (operands[1]) % 16 == 0"
1085   "movk\\t%<w>0, %X2, lsl %1"
1086   [(set_attr "type" "mov_imm")]
1089 (define_expand "movti"
1090   [(set (match_operand:TI 0 "nonimmediate_operand" "")
1091         (match_operand:TI 1 "general_operand" ""))]
1092   ""
1093   "
1094     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1095       operands[1] = force_reg (TImode, operands[1]);
1097     if (GET_CODE (operands[1]) == CONST_POLY_INT)
1098       {
1099         emit_move_insn (gen_lowpart (DImode, operands[0]),
1100                         gen_lowpart (DImode, operands[1]));
1101         emit_move_insn (gen_highpart (DImode, operands[0]), const0_rtx);
1102         DONE;
1103       }
1104   "
1107 (define_insn "*movti_aarch64"
1108   [(set (match_operand:TI 0
1109          "nonimmediate_operand"  "=   r,w, r,w,r,m,m,w,m")
1110         (match_operand:TI 1
1111          "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
1112   "(register_operand (operands[0], TImode)
1113     || aarch64_reg_or_zero (operands[1], TImode))"
1114   "@
1115    #
1116    #
1117    #
1118    mov\\t%0.16b, %1.16b
1119    ldp\\t%0, %H0, %1
1120    stp\\t%1, %H1, %0
1121    stp\\txzr, xzr, %0
1122    ldr\\t%q0, %1
1123    str\\t%q1, %0"
1124   [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1125                              load_16,store_16,store_16,\
1126                              load_16,store_16")
1127    (set_attr "length" "8,8,8,4,4,4,4,4,4")
1128    (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1129    (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1132 ;; Split a TImode register-register or register-immediate move into
1133 ;; its component DImode pieces, taking care to handle overlapping
1134 ;; source and dest registers.
1135 (define_split
1136    [(set (match_operand:TI 0 "register_operand" "")
1137          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1138   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1139   [(const_int 0)]
1141   aarch64_split_128bit_move (operands[0], operands[1]);
1142   DONE;
1145 (define_expand "mov<mode>"
1146   [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1147         (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1148   ""
1149   {
1150     if (!TARGET_FLOAT)
1151       {
1152         aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1153         FAIL;
1154       }
1156     if (GET_CODE (operands[0]) == MEM
1157         && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1158               && aarch64_float_const_zero_rtx_p (operands[1])))
1159       operands[1] = force_reg (<MODE>mode, operands[1]);
1160   }
1163 (define_insn "*movhf_aarch64"
1164   [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r")
1165         (match_operand:HF 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1166   "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1167     || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1168   "@
1169    movi\\t%0.4h, #0
1170    fmov\\t%h0, %w1
1171    umov\\t%w0, %1.h[0]
1172    mov\\t%0.h[0], %1.h[0]
1173    fmov\\t%h0, %1
1174    * return aarch64_output_scalar_simd_mov_immediate (operands[1], HImode);
1175    ldr\\t%h0, %1
1176    str\\t%h1, %0
1177    ldrh\\t%w0, %1
1178    strh\\t%w1, %0
1179    mov\\t%w0, %w1"
1180   [(set_attr "type" "neon_move,f_mcr,neon_to_gp,neon_move,fconsts, \
1181                      neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1182    (set_attr "simd" "yes,*,yes,yes,*,yes,*,*,*,*,*")
1183    (set_attr "fp16"   "*,yes,*,*,yes,*,*,*,*,*,*")]
1186 (define_insn "*movsf_aarch64"
1187   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
1188         (match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1189   "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1190     || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1191   "@
1192    movi\\t%0.2s, #0
1193    fmov\\t%s0, %w1
1194    fmov\\t%w0, %s1
1195    fmov\\t%s0, %s1
1196    fmov\\t%s0, %1
1197    * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1198    ldr\\t%s0, %1
1199    str\\t%s1, %0
1200    ldr\\t%w0, %1
1201    str\\t%w1, %0
1202    mov\\t%w0, %w1
1203    mov\\t%w0, %1"
1204   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1205                      f_loads,f_stores,load_4,store_4,mov_reg,\
1206                      fconsts")
1207    (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1210 (define_insn "*movdf_aarch64"
1211   [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
1212         (match_operand:DF 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1213   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1214     || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1215   "@
1216    movi\\t%d0, #0
1217    fmov\\t%d0, %x1
1218    fmov\\t%x0, %d1
1219    fmov\\t%d0, %d1
1220    fmov\\t%d0, %1
1221    * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
1222    ldr\\t%d0, %1
1223    str\\t%d1, %0
1224    ldr\\t%x0, %1
1225    str\\t%x1, %0
1226    mov\\t%x0, %x1
1227    mov\\t%x0, %1"
1228   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1229                      f_loadd,f_stored,load_8,store_8,mov_reg,\
1230                      fconstd")
1231    (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1234 (define_split
1235   [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
1236         (match_operand:GPF_HF 1 "general_operand"))]
1237   "can_create_pseudo_p ()
1238    && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
1239    && !aarch64_float_const_representable_p (operands[1])
1240    &&  aarch64_float_const_rtx_p (operands[1])"
1241   [(const_int 0)]
1242   {
1243     unsigned HOST_WIDE_INT ival;
1244     if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
1245       FAIL;
1247     rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1248     emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1249     emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
1250     DONE;
1251   }
1254 (define_insn "*movtf_aarch64"
1255   [(set (match_operand:TF 0
1256          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1257         (match_operand:TF 1
1258          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1259   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1260     || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1261   "@
1262    mov\\t%0.16b, %1.16b
1263    #
1264    #
1265    #
1266    movi\\t%0.2d, #0
1267    fmov\\t%s0, wzr
1268    ldr\\t%q0, %1
1269    str\\t%q1, %0
1270    ldp\\t%0, %H0, %1
1271    stp\\t%1, %H1, %0
1272    stp\\txzr, xzr, %0"
1273   [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1274                      f_loadd,f_stored,load_16,store_16,store_16")
1275    (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1276    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1279 (define_split
1280    [(set (match_operand:TF 0 "register_operand" "")
1281          (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1282   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1283   [(const_int 0)]
1284   {
1285     aarch64_split_128bit_move (operands[0], operands[1]);
1286     DONE;
1287   }
1290 ;; 0 is dst
1291 ;; 1 is src
1292 ;; 2 is size of move in bytes
1293 ;; 3 is alignment
1295 (define_expand "movmemdi"
1296   [(match_operand:BLK 0 "memory_operand")
1297    (match_operand:BLK 1 "memory_operand")
1298    (match_operand:DI 2 "immediate_operand")
1299    (match_operand:DI 3 "immediate_operand")]
1300    "!STRICT_ALIGNMENT"
1302   if (aarch64_expand_movmem (operands))
1303     DONE;
1304   FAIL;
1308 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1309 ;; fairly lax checking on the second memory operation.
1310 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1311   [(set (match_operand:SX 0 "register_operand" "=r,w")
1312         (match_operand:SX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1313    (set (match_operand:SX2 2 "register_operand" "=r,w")
1314         (match_operand:SX2 3 "memory_operand" "m,m"))]
1315    "rtx_equal_p (XEXP (operands[3], 0),
1316                  plus_constant (Pmode,
1317                                 XEXP (operands[1], 0),
1318                                 GET_MODE_SIZE (<SX:MODE>mode)))"
1319   "@
1320    ldp\\t%w0, %w2, %1
1321    ldp\\t%s0, %s2, %1"
1322   [(set_attr "type" "load_8,neon_load1_2reg")
1323    (set_attr "fp" "*,yes")]
1326 ;; Storing different modes that can still be merged
1327 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1328   [(set (match_operand:DX 0 "register_operand" "=r,w")
1329         (match_operand:DX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1330    (set (match_operand:DX2 2 "register_operand" "=r,w")
1331         (match_operand:DX2 3 "memory_operand" "m,m"))]
1332    "rtx_equal_p (XEXP (operands[3], 0),
1333                  plus_constant (Pmode,
1334                                 XEXP (operands[1], 0),
1335                                 GET_MODE_SIZE (<DX:MODE>mode)))"
1336   "@
1337    ldp\\t%x0, %x2, %1
1338    ldp\\t%d0, %d2, %1"
1339   [(set_attr "type" "load_16,neon_load1_2reg")
1340    (set_attr "fp" "*,yes")]
1343 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1344 ;; fairly lax checking on the second memory operation.
1345 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1346   [(set (match_operand:SX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1347         (match_operand:SX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1348    (set (match_operand:SX2 2 "memory_operand" "=m,m")
1349         (match_operand:SX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1350    "rtx_equal_p (XEXP (operands[2], 0),
1351                  plus_constant (Pmode,
1352                                 XEXP (operands[0], 0),
1353                                 GET_MODE_SIZE (<SX:MODE>mode)))"
1354   "@
1355    stp\\t%w1, %w3, %0
1356    stp\\t%s1, %s3, %0"
1357   [(set_attr "type" "store_8,neon_store1_2reg")
1358    (set_attr "fp" "*,yes")]
1361 ;; Storing different modes that can still be merged
1362 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1363   [(set (match_operand:DX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1364         (match_operand:DX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1365    (set (match_operand:DX2 2 "memory_operand" "=m,m")
1366         (match_operand:DX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1367    "rtx_equal_p (XEXP (operands[2], 0),
1368                  plus_constant (Pmode,
1369                                 XEXP (operands[0], 0),
1370                                 GET_MODE_SIZE (<DX:MODE>mode)))"
1371   "@
1372    stp\\t%x1, %x3, %0
1373    stp\\t%d1, %d3, %0"
1374   [(set_attr "type" "store_16,neon_store1_2reg")
1375    (set_attr "fp" "*,yes")]
1378 ;; Load pair with post-index writeback.  This is primarily used in function
1379 ;; epilogues.
1380 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1381   [(parallel
1382     [(set (match_operand:P 0 "register_operand" "=k")
1383           (plus:P (match_operand:P 1 "register_operand" "0")
1384                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1385      (set (match_operand:GPI 2 "register_operand" "=r")
1386           (mem:GPI (match_dup 1)))
1387      (set (match_operand:GPI 3 "register_operand" "=r")
1388           (mem:GPI (plus:P (match_dup 1)
1389                    (match_operand:P 5 "const_int_operand" "n"))))])]
1390   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1391   "ldp\\t%<w>2, %<w>3, [%1], %4"
1392   [(set_attr "type" "load_<ldpstp_sz>")]
1395 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1396   [(parallel
1397     [(set (match_operand:P 0 "register_operand" "=k")
1398           (plus:P (match_operand:P 1 "register_operand" "0")
1399                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1400      (set (match_operand:GPF 2 "register_operand" "=w")
1401           (mem:GPF (match_dup 1)))
1402      (set (match_operand:GPF 3 "register_operand" "=w")
1403           (mem:GPF (plus:P (match_dup 1)
1404                    (match_operand:P 5 "const_int_operand" "n"))))])]
1405   "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1406   "ldp\\t%<w>2, %<w>3, [%1], %4"
1407   [(set_attr "type" "neon_load1_2reg")]
1410 ;; Store pair with pre-index writeback.  This is primarily used in function
1411 ;; prologues.
1412 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1413   [(parallel
1414     [(set (match_operand:P 0 "register_operand" "=&k")
1415           (plus:P (match_operand:P 1 "register_operand" "0")
1416                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1417      (set (mem:GPI (plus:P (match_dup 0)
1418                    (match_dup 4)))
1419           (match_operand:GPI 2 "register_operand" "r"))
1420      (set (mem:GPI (plus:P (match_dup 0)
1421                    (match_operand:P 5 "const_int_operand" "n")))
1422           (match_operand:GPI 3 "register_operand" "r"))])]
1423   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1424   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1425   [(set_attr "type" "store_<ldpstp_sz>")]
1428 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1429   [(parallel
1430     [(set (match_operand:P 0 "register_operand" "=&k")
1431           (plus:P (match_operand:P 1 "register_operand" "0")
1432                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1433      (set (mem:GPF (plus:P (match_dup 0)
1434                    (match_dup 4)))
1435           (match_operand:GPF 2 "register_operand" "w"))
1436      (set (mem:GPF (plus:P (match_dup 0)
1437                    (match_operand:P 5 "const_int_operand" "n")))
1438           (match_operand:GPF 3 "register_operand" "w"))])]
1439   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1440   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1441   [(set_attr "type" "neon_store1_2reg<q>")]
1444 ;; -------------------------------------------------------------------
1445 ;; Sign/Zero extension
1446 ;; -------------------------------------------------------------------
1448 (define_expand "<optab>sidi2"
1449   [(set (match_operand:DI 0 "register_operand")
1450         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1451   ""
1454 (define_insn "*extendsidi2_aarch64"
1455   [(set (match_operand:DI 0 "register_operand" "=r,r")
1456         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1457   ""
1458   "@
1459    sxtw\t%0, %w1
1460    ldrsw\t%0, %1"
1461   [(set_attr "type" "extend,load_4")]
1464 (define_insn "*load_pair_extendsidi2_aarch64"
1465   [(set (match_operand:DI 0 "register_operand" "=r")
1466         (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1467    (set (match_operand:DI 2 "register_operand" "=r")
1468         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1469   "rtx_equal_p (XEXP (operands[3], 0),
1470                 plus_constant (Pmode,
1471                                XEXP (operands[1], 0),
1472                                GET_MODE_SIZE (SImode)))"
1473   "ldpsw\\t%0, %2, %1"
1474   [(set_attr "type" "load_8")]
1477 (define_insn "*zero_extendsidi2_aarch64"
1478   [(set (match_operand:DI 0 "register_operand" "=r,r")
1479         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1480   ""
1481   "@
1482    uxtw\t%0, %w1
1483    ldr\t%w0, %1"
1484   [(set_attr "type" "extend,load_4")]
1487 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1488   [(set (match_operand:DI 0 "register_operand" "=r")
1489         (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1490    (set (match_operand:DI 2 "register_operand" "=r")
1491         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1492   "rtx_equal_p (XEXP (operands[3], 0),
1493                 plus_constant (Pmode,
1494                                XEXP (operands[1], 0),
1495                                GET_MODE_SIZE (SImode)))"
1496   "ldp\\t%w0, %w2, %1"
1497   [(set_attr "type" "load_8")]
1500 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1501   [(set (match_operand:GPI 0 "register_operand")
1502         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1503   ""
1506 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1507   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1508         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1509   ""
1510   "@
1511    sxt<SHORT:size>\t%<GPI:w>0, %w1
1512    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1513   [(set_attr "type" "extend,load_4")]
1516 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1517   [(set (match_operand:GPI 0 "register_operand" "=r,r,w")
1518         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1519   ""
1520   "@
1521    and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1522    ldr<SHORT:size>\t%w0, %1
1523    ldr\t%<SHORT:size>0, %1"
1524   [(set_attr "type" "logic_imm,load_4,load_4")]
1527 (define_expand "<optab>qihi2"
1528   [(set (match_operand:HI 0 "register_operand")
1529         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1530   ""
1533 (define_insn "*extendqihi2_aarch64"
1534   [(set (match_operand:HI 0 "register_operand" "=r,r")
1535         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1536   ""
1537   "@
1538    sxtb\t%w0, %w1
1539    ldrsb\t%w0, %1"
1540   [(set_attr "type" "extend,load_4")]
1543 (define_insn "*zero_extendqihi2_aarch64"
1544   [(set (match_operand:HI 0 "register_operand" "=r,r")
1545         (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1546   ""
1547   "@
1548    and\t%w0, %w1, 255
1549    ldrb\t%w0, %1"
1550   [(set_attr "type" "logic_imm,load_4")]
1553 ;; -------------------------------------------------------------------
1554 ;; Simple arithmetic
1555 ;; -------------------------------------------------------------------
1557 (define_expand "add<mode>3"
1558   [(set
1559     (match_operand:GPI 0 "register_operand" "")
1560     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1561               (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "")))]
1562   ""
1564   /* If operands[1] is a subreg extract the inner RTX.  */
1565   rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1567   /* If the constant is too large for a single instruction and isn't frame
1568      based, split off the immediate so it is available for CSE.  */
1569   if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1570       && can_create_pseudo_p ()
1571       && (!REG_P (op1)
1572          || !REGNO_PTR_FRAME_P (REGNO (op1))))
1573     operands[2] = force_reg (<MODE>mode, operands[2]);
1574   /* Expand polynomial additions now if the destination is the stack
1575      pointer, since we don't want to use that as a temporary.  */
1576   else if (operands[0] == stack_pointer_rtx
1577            && aarch64_split_add_offset_immediate (operands[2], <MODE>mode))
1578     {
1579       aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
1580                                 operands[2], NULL_RTX, NULL_RTX);
1581       DONE;
1582     }
1585 (define_insn "*add<mode>3_aarch64"
1586   [(set
1587     (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r,rk")
1588     (plus:GPI
1589      (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk,rk")
1590      (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uav")))]
1591   ""
1592   "@
1593   add\\t%<w>0, %<w>1, %2
1594   add\\t%<w>0, %<w>1, %<w>2
1595   add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1596   sub\\t%<w>0, %<w>1, #%n2
1597   #
1598   * return aarch64_output_sve_addvl_addpl (operands[0], operands[1], operands[2]);"
1599   ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1600   [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm")
1601    (set_attr "simd" "*,*,yes,*,*,*")]
1604 ;; zero_extend version of above
1605 (define_insn "*addsi3_aarch64_uxtw"
1606   [(set
1607     (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1608     (zero_extend:DI
1609      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1610               (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1611   ""
1612   "@
1613   add\\t%w0, %w1, %2
1614   add\\t%w0, %w1, %w2
1615   sub\\t%w0, %w1, #%n2
1616   #"
1617   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1620 ;; If there's a free register, and we can load the constant with a
1621 ;; single instruction, do so.  This has a chance to improve scheduling.
1622 (define_peephole2
1623   [(match_scratch:GPI 3 "r")
1624    (set (match_operand:GPI 0 "register_operand")
1625         (plus:GPI
1626           (match_operand:GPI 1 "register_operand")
1627           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1628   "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1629   [(set (match_dup 3) (match_dup 2))
1630    (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1633 (define_peephole2
1634   [(match_scratch:SI 3 "r")
1635    (set (match_operand:DI 0 "register_operand")
1636         (zero_extend:DI
1637           (plus:SI
1638             (match_operand:SI 1 "register_operand")
1639             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1640   "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1641   [(set (match_dup 3) (match_dup 2))
1642    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1645 ;; After peephole2 has had a chance to run, split any remaining long
1646 ;; additions into two add immediates.
1647 (define_split
1648   [(set (match_operand:GPI 0 "register_operand")
1649         (plus:GPI
1650           (match_operand:GPI 1 "register_operand")
1651           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1652   "epilogue_completed"
1653   [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1654    (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1655   {
1656     HOST_WIDE_INT i = INTVAL (operands[2]);
1657     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1658     operands[3] = GEN_INT (i - s);
1659     operands[4] = GEN_INT (s);
1660   }
1663 ;; Match addition of polynomial offsets that require one temporary, for which
1664 ;; we can use the early-clobbered destination register.  This is a separate
1665 ;; pattern so that the early clobber doesn't affect register allocation
1666 ;; for other forms of addition.  However, we still need to provide an
1667 ;; all-register alternative, in case the offset goes out of range after
1668 ;; elimination.  For completeness we might as well provide all GPR-based
1669 ;; alternatives from the main pattern.
1671 ;; We don't have a pattern for additions requiring two temporaries since at
1672 ;; present LRA doesn't allow new scratches to be added during elimination.
1673 ;; Such offsets should be rare anyway.
1675 ;; ??? But if we added LRA support for new scratches, much of the ugliness
1676 ;; here would go away.  We could just handle all polynomial constants in
1677 ;; this pattern.
1678 (define_insn_and_split "*add<mode>3_poly_1"
1679   [(set
1680     (match_operand:GPI 0 "register_operand" "=r,r,r,r,r,&r")
1681     (plus:GPI
1682      (match_operand:GPI 1 "register_operand" "%rk,rk,rk,rk,rk,rk")
1683      (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uat")))]
1684   "TARGET_SVE && operands[0] != stack_pointer_rtx"
1685   "@
1686   add\\t%<w>0, %<w>1, %2
1687   add\\t%<w>0, %<w>1, %<w>2
1688   sub\\t%<w>0, %<w>1, #%n2
1689   #
1690   * return aarch64_output_sve_addvl_addpl (operands[0], operands[1], operands[2]);
1691   #"
1692   "&& epilogue_completed
1693    && !reg_overlap_mentioned_p (operands[0], operands[1])
1694    && aarch64_split_add_offset_immediate (operands[2], <MODE>mode)"
1695   [(const_int 0)]
1696   {
1697     aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
1698                               operands[2], operands[0], NULL_RTX);
1699     DONE;
1700   }
1701   ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1702   [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,multiple")]
1705 (define_split
1706   [(set (match_operand:DI 0 "register_operand")
1707         (zero_extend:DI
1708           (plus:SI
1709             (match_operand:SI 1 "register_operand")
1710             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1711   "epilogue_completed"
1712   [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1713    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1714   {
1715     HOST_WIDE_INT i = INTVAL (operands[2]);
1716     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1717     operands[3] = GEN_INT (i - s);
1718     operands[4] = GEN_INT (s);
1719     operands[5] = gen_lowpart (SImode, operands[0]);
1720   }
1723 (define_expand "addti3"
1724   [(set (match_operand:TI 0 "register_operand" "")
1725         (plus:TI (match_operand:TI 1 "register_operand" "")
1726                  (match_operand:TI 2 "register_operand" "")))]
1727   ""
1729   rtx low = gen_reg_rtx (DImode);
1730   emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1731                                   gen_lowpart (DImode, operands[2])));
1733   rtx high = gen_reg_rtx (DImode);
1734   emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1735                                  gen_highpart (DImode, operands[2])));
1737   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1738   emit_move_insn (gen_highpart (DImode, operands[0]), high);
1739   DONE;
1742 (define_insn "add<mode>3_compare0"
1743   [(set (reg:CC_NZ CC_REGNUM)
1744         (compare:CC_NZ
1745          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1746                    (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1747          (const_int 0)))
1748    (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1749         (plus:GPI (match_dup 1) (match_dup 2)))]
1750   ""
1751   "@
1752   adds\\t%<w>0, %<w>1, %<w>2
1753   adds\\t%<w>0, %<w>1, %2
1754   subs\\t%<w>0, %<w>1, #%n2"
1755   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1758 ;; zero_extend version of above
1759 (define_insn "*addsi3_compare0_uxtw"
1760   [(set (reg:CC_NZ CC_REGNUM)
1761         (compare:CC_NZ
1762          (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1763                   (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1764          (const_int 0)))
1765    (set (match_operand:DI 0 "register_operand" "=r,r,r")
1766         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1767   ""
1768   "@
1769   adds\\t%w0, %w1, %w2
1770   adds\\t%w0, %w1, %2
1771   subs\\t%w0, %w1, #%n2"
1772   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1775 (define_insn "*add<mode>3_compareC_cconly_imm"
1776   [(set (reg:CC_C CC_REGNUM)
1777         (ne:CC_C
1778           (plus:<DWI>
1779             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1780             (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1781           (zero_extend:<DWI>
1782             (plus:GPI
1783               (match_dup 0)
1784               (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1785   "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1786                                  <MODE>mode, operands[1])"
1787   "@
1788   cmn\\t%<w>0, %1
1789   cmp\\t%<w>0, #%n1"
1790   [(set_attr "type" "alus_imm")]
1793 (define_insn "*add<mode>3_compareC_cconly"
1794   [(set (reg:CC_C CC_REGNUM)
1795         (ne:CC_C
1796           (plus:<DWI>
1797             (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1798             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1799           (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1800   ""
1801   "cmn\\t%<w>0, %<w>1"
1802   [(set_attr "type" "alus_sreg")]
1805 (define_insn "*add<mode>3_compareC_imm"
1806   [(set (reg:CC_C CC_REGNUM)
1807         (ne:CC_C
1808           (plus:<DWI>
1809             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1810             (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1811           (zero_extend:<DWI>
1812             (plus:GPI
1813               (match_dup 1)
1814               (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1815    (set (match_operand:GPI 0 "register_operand" "=r,r")
1816         (plus:GPI (match_dup 1) (match_dup 2)))]
1817   "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1818                                  <MODE>mode, operands[2])"
1819   "@
1820   adds\\t%<w>0, %<w>1, %2
1821   subs\\t%<w>0, %<w>1, #%n2"
1822   [(set_attr "type" "alus_imm")]
1825 (define_insn "add<mode>3_compareC"
1826   [(set (reg:CC_C CC_REGNUM)
1827         (ne:CC_C
1828           (plus:<DWI>
1829             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1830             (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1831           (zero_extend:<DWI>
1832             (plus:GPI (match_dup 1) (match_dup 2)))))
1833    (set (match_operand:GPI 0 "register_operand" "=r")
1834         (plus:GPI (match_dup 1) (match_dup 2)))]
1835   ""
1836   "adds\\t%<w>0, %<w>1, %<w>2"
1837   [(set_attr "type" "alus_sreg")]
1840 (define_insn "*adds_shift_imm_<mode>"
1841   [(set (reg:CC_NZ CC_REGNUM)
1842         (compare:CC_NZ
1843          (plus:GPI (ASHIFT:GPI 
1844                     (match_operand:GPI 1 "register_operand" "r")
1845                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1846                    (match_operand:GPI 3 "register_operand" "r"))
1847          (const_int 0)))
1848    (set (match_operand:GPI 0 "register_operand" "=r")
1849         (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1850                   (match_dup 3)))]
1851   ""
1852   "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1853   [(set_attr "type" "alus_shift_imm")]
1856 (define_insn "*subs_shift_imm_<mode>"
1857   [(set (reg:CC_NZ CC_REGNUM)
1858         (compare:CC_NZ
1859          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1860                     (ASHIFT:GPI
1861                      (match_operand:GPI 2 "register_operand" "r")
1862                      (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1863          (const_int 0)))
1864    (set (match_operand:GPI 0 "register_operand" "=r")
1865         (minus:GPI (match_dup 1)
1866                    (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1867   ""
1868   "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1869   [(set_attr "type" "alus_shift_imm")]
1872 (define_insn "*adds_mul_imm_<mode>"
1873   [(set (reg:CC_NZ CC_REGNUM)
1874         (compare:CC_NZ
1875          (plus:GPI (mult:GPI
1876                     (match_operand:GPI 1 "register_operand" "r")
1877                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1878                    (match_operand:GPI 3 "register_operand" "r"))
1879          (const_int 0)))
1880    (set (match_operand:GPI 0 "register_operand" "=r")
1881         (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1882                   (match_dup 3)))]
1883   ""
1884   "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1885   [(set_attr "type" "alus_shift_imm")]
1888 (define_insn "*subs_mul_imm_<mode>"
1889   [(set (reg:CC_NZ CC_REGNUM)
1890         (compare:CC_NZ
1891          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1892                     (mult:GPI
1893                      (match_operand:GPI 2 "register_operand" "r")
1894                      (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1895          (const_int 0)))
1896    (set (match_operand:GPI 0 "register_operand" "=r")
1897         (minus:GPI (match_dup 1)
1898                    (mult:GPI (match_dup 2) (match_dup 3))))]
1899   ""
1900   "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1901   [(set_attr "type" "alus_shift_imm")]
1904 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1905   [(set (reg:CC_NZ CC_REGNUM)
1906         (compare:CC_NZ
1907          (plus:GPI
1908           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1909           (match_operand:GPI 2 "register_operand" "r"))
1910         (const_int 0)))
1911    (set (match_operand:GPI 0 "register_operand" "=r")
1912         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1913   ""
1914   "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1915   [(set_attr "type" "alus_ext")]
1918 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1919   [(set (reg:CC_NZ CC_REGNUM)
1920         (compare:CC_NZ
1921          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1922                     (ANY_EXTEND:GPI
1923                      (match_operand:ALLX 2 "register_operand" "r")))
1924         (const_int 0)))
1925    (set (match_operand:GPI 0 "register_operand" "=r")
1926         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1927   ""
1928   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1929   [(set_attr "type" "alus_ext")]
1932 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1933   [(set (reg:CC_NZ CC_REGNUM)
1934         (compare:CC_NZ
1935          (plus:GPI (ashift:GPI 
1936                     (ANY_EXTEND:GPI 
1937                      (match_operand:ALLX 1 "register_operand" "r"))
1938                     (match_operand 2 "aarch64_imm3" "Ui3"))
1939                    (match_operand:GPI 3 "register_operand" "r"))
1940          (const_int 0)))
1941    (set (match_operand:GPI 0 "register_operand" "=rk")
1942         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1943                               (match_dup 2))
1944                   (match_dup 3)))]
1945   ""
1946   "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1947   [(set_attr "type" "alus_ext")]
1950 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1951   [(set (reg:CC_NZ CC_REGNUM)
1952         (compare:CC_NZ
1953          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1954                     (ashift:GPI 
1955                      (ANY_EXTEND:GPI
1956                       (match_operand:ALLX 2 "register_operand" "r"))
1957                      (match_operand 3 "aarch64_imm3" "Ui3")))
1958          (const_int 0)))
1959    (set (match_operand:GPI 0 "register_operand" "=rk")
1960         (minus:GPI (match_dup 1)
1961                    (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1962                                (match_dup 3))))]
1963   ""
1964   "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1965   [(set_attr "type" "alus_ext")]
1968 (define_insn "*adds_<optab><mode>_multp2"
1969   [(set (reg:CC_NZ CC_REGNUM)
1970         (compare:CC_NZ
1971          (plus:GPI (ANY_EXTRACT:GPI
1972                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1973                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1974                     (match_operand 3 "const_int_operand" "n")
1975                     (const_int 0))
1976                    (match_operand:GPI 4 "register_operand" "r"))
1977         (const_int 0)))
1978    (set (match_operand:GPI 0 "register_operand" "=r")
1979         (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1980                                    (match_dup 3)
1981                                    (const_int 0))
1982                   (match_dup 4)))]
1983   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1984   "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1985   [(set_attr "type" "alus_ext")]
1988 (define_insn "*subs_<optab><mode>_multp2"
1989   [(set (reg:CC_NZ CC_REGNUM)
1990         (compare:CC_NZ
1991          (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1992                     (ANY_EXTRACT:GPI
1993                      (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1994                                (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1995                      (match_operand 3 "const_int_operand" "n")
1996                      (const_int 0)))
1997         (const_int 0)))
1998    (set (match_operand:GPI 0 "register_operand" "=r")
1999         (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
2000                                   (mult:GPI (match_dup 1) (match_dup 2))
2001                                   (match_dup 3)
2002                                   (const_int 0))))]
2003   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2004   "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2005   [(set_attr "type" "alus_ext")]
2008 (define_insn "*add<mode>3nr_compare0"
2009   [(set (reg:CC_NZ CC_REGNUM)
2010         (compare:CC_NZ
2011          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2012                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2013          (const_int 0)))]
2014   ""
2015   "@
2016   cmn\\t%<w>0, %<w>1
2017   cmn\\t%<w>0, %1
2018   cmp\\t%<w>0, #%n1"
2019   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2022 (define_insn "aarch64_sub<mode>_compare0"
2023   [(set (reg:CC_NZ CC_REGNUM)
2024         (compare:CC_NZ
2025          (minus:GPI (match_operand:GPI 0 "register_operand" "r")
2026                    (match_operand:GPI 1 "aarch64_plus_operand" "r"))
2027          (const_int 0)))]
2028   ""
2029   "cmp\\t%<w>0, %<w>1"
2030   [(set_attr "type" "alus_sreg")]
2033 (define_insn "*compare_neg<mode>"
2034   [(set (reg:CC_Z CC_REGNUM)
2035         (compare:CC_Z
2036          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2037          (match_operand:GPI 1 "register_operand" "r")))]
2038   ""
2039   "cmn\\t%<w>1, %<w>0"
2040   [(set_attr "type" "alus_sreg")]
2043 (define_insn "*add_<shift>_<mode>"
2044   [(set (match_operand:GPI 0 "register_operand" "=r")
2045         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2046                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2047                   (match_operand:GPI 3 "register_operand" "r")))]
2048   ""
2049   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2050   [(set_attr "type" "alu_shift_imm")]
2053 ;; zero_extend version of above
2054 (define_insn "*add_<shift>_si_uxtw"
2055   [(set (match_operand:DI 0 "register_operand" "=r")
2056         (zero_extend:DI
2057          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2058                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2059                   (match_operand:SI 3 "register_operand" "r"))))]
2060   ""
2061   "add\\t%w0, %w3, %w1, <shift> %2"
2062   [(set_attr "type" "alu_shift_imm")]
2065 (define_insn "*add_mul_imm_<mode>"
2066   [(set (match_operand:GPI 0 "register_operand" "=r")
2067         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2068                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2069                   (match_operand:GPI 3 "register_operand" "r")))]
2070   ""
2071   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2072   [(set_attr "type" "alu_shift_imm")]
2075 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2076   [(set (match_operand:GPI 0 "register_operand" "=rk")
2077         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2078                   (match_operand:GPI 2 "register_operand" "r")))]
2079   ""
2080   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2081   [(set_attr "type" "alu_ext")]
2084 ;; zero_extend version of above
2085 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2086   [(set (match_operand:DI 0 "register_operand" "=rk")
2087         (zero_extend:DI
2088          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2089                   (match_operand:GPI 2 "register_operand" "r"))))]
2090   ""
2091   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2092   [(set_attr "type" "alu_ext")]
2095 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2096   [(set (match_operand:GPI 0 "register_operand" "=rk")
2097         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2098                                (match_operand:ALLX 1 "register_operand" "r"))
2099                               (match_operand 2 "aarch64_imm3" "Ui3"))
2100                   (match_operand:GPI 3 "register_operand" "r")))]
2101   ""
2102   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2103   [(set_attr "type" "alu_ext")]
2106 ;; zero_extend version of above
2107 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2108   [(set (match_operand:DI 0 "register_operand" "=rk")
2109         (zero_extend:DI
2110          (plus:SI (ashift:SI (ANY_EXTEND:SI
2111                               (match_operand:SHORT 1 "register_operand" "r"))
2112                              (match_operand 2 "aarch64_imm3" "Ui3"))
2113                   (match_operand:SI 3 "register_operand" "r"))))]
2114   ""
2115   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2116   [(set_attr "type" "alu_ext")]
2119 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2120   [(set (match_operand:GPI 0 "register_operand" "=rk")
2121         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2122                              (match_operand:ALLX 1 "register_operand" "r"))
2123                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2124                   (match_operand:GPI 3 "register_operand" "r")))]
2125   ""
2126   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2127   [(set_attr "type" "alu_ext")]
2130 ;; zero_extend version of above
2131 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2132   [(set (match_operand:DI 0 "register_operand" "=rk")
2133         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2134                              (match_operand:SHORT 1 "register_operand" "r"))
2135                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2136                   (match_operand:SI 3 "register_operand" "r"))))]
2137   ""
2138   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2139   [(set_attr "type" "alu_ext")]
2142 (define_insn "*add_<optab><mode>_multp2"
2143   [(set (match_operand:GPI 0 "register_operand" "=rk")
2144         (plus:GPI (ANY_EXTRACT:GPI
2145                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2146                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2147                    (match_operand 3 "const_int_operand" "n")
2148                    (const_int 0))
2149                   (match_operand:GPI 4 "register_operand" "r")))]
2150   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2151   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2152   [(set_attr "type" "alu_ext")]
2155 ;; zero_extend version of above
2156 (define_insn "*add_<optab>si_multp2_uxtw"
2157   [(set (match_operand:DI 0 "register_operand" "=rk")
2158         (zero_extend:DI
2159          (plus:SI (ANY_EXTRACT:SI
2160                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2161                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2162                    (match_operand 3 "const_int_operand" "n")
2163                    (const_int 0))
2164                   (match_operand:SI 4 "register_operand" "r"))))]
2165   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2166   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2167   [(set_attr "type" "alu_ext")]
2170 (define_expand "add<mode>3_carryin"
2171   [(set (match_operand:GPI 0 "register_operand")
2172         (plus:GPI
2173           (plus:GPI
2174             (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2175             (match_operand:GPI 1 "aarch64_reg_or_zero"))
2176           (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2177    ""
2178    ""
2181 ;; Note that add with carry with two zero inputs is matched by cset,
2182 ;; and that add with carry with one zero input is matched by cinc.
2184 (define_insn "*add<mode>3_carryin"
2185   [(set (match_operand:GPI 0 "register_operand" "=r")
2186         (plus:GPI
2187           (plus:GPI
2188             (match_operand:GPI 3 "aarch64_carry_operation" "")
2189             (match_operand:GPI 1 "register_operand" "r"))
2190           (match_operand:GPI 2 "register_operand" "r")))]
2191    ""
2192    "adc\\t%<w>0, %<w>1, %<w>2"
2193   [(set_attr "type" "adc_reg")]
2196 ;; zero_extend version of above
2197 (define_insn "*addsi3_carryin_uxtw"
2198   [(set (match_operand:DI 0 "register_operand" "=r")
2199         (zero_extend:DI
2200           (plus:SI
2201             (plus:SI
2202               (match_operand:SI 3 "aarch64_carry_operation" "")
2203               (match_operand:SI 1 "register_operand" "r"))
2204             (match_operand:SI 2 "register_operand" "r"))))]
2205    ""
2206    "adc\\t%w0, %w1, %w2"
2207   [(set_attr "type" "adc_reg")]
2210 (define_insn "*add_uxt<mode>_shift2"
2211   [(set (match_operand:GPI 0 "register_operand" "=rk")
2212         (plus:GPI (and:GPI
2213                    (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2214                                (match_operand 2 "aarch64_imm3" "Ui3"))
2215                    (match_operand 3 "const_int_operand" "n"))
2216                   (match_operand:GPI 4 "register_operand" "r")))]
2217   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2218   "*
2219   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2220                                            INTVAL (operands[3])));
2221   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2222   [(set_attr "type" "alu_ext")]
2225 ;; zero_extend version of above
2226 (define_insn "*add_uxtsi_shift2_uxtw"
2227   [(set (match_operand:DI 0 "register_operand" "=rk")
2228         (zero_extend:DI
2229          (plus:SI (and:SI
2230                    (ashift:SI (match_operand:SI 1 "register_operand" "r")
2231                               (match_operand 2 "aarch64_imm3" "Ui3"))
2232                    (match_operand 3 "const_int_operand" "n"))
2233                   (match_operand:SI 4 "register_operand" "r"))))]
2234   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2235   "*
2236   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2237                                            INTVAL (operands[3])));
2238   return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2239   [(set_attr "type" "alu_ext")]
2242 (define_insn "*add_uxt<mode>_multp2"
2243   [(set (match_operand:GPI 0 "register_operand" "=rk")
2244         (plus:GPI (and:GPI
2245                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2246                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2247                    (match_operand 3 "const_int_operand" "n"))
2248                   (match_operand:GPI 4 "register_operand" "r")))]
2249   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2250   "*
2251   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2252                                            INTVAL (operands[3])));
2253   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2254   [(set_attr "type" "alu_ext")]
2257 ;; zero_extend version of above
2258 (define_insn "*add_uxtsi_multp2_uxtw"
2259   [(set (match_operand:DI 0 "register_operand" "=rk")
2260         (zero_extend:DI
2261          (plus:SI (and:SI
2262                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2263                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2264                    (match_operand 3 "const_int_operand" "n"))
2265                   (match_operand:SI 4 "register_operand" "r"))))]
2266   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2267   "*
2268   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2269                                            INTVAL (operands[3])));
2270   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2271   [(set_attr "type" "alu_ext")]
2274 (define_insn "subsi3"
2275   [(set (match_operand:SI 0 "register_operand" "=rk")
2276         (minus:SI (match_operand:SI 1 "register_operand" "rk")
2277                   (match_operand:SI 2 "register_operand" "r")))]
2278   ""
2279   "sub\\t%w0, %w1, %w2"
2280   [(set_attr "type" "alu_sreg")]
2283 ;; zero_extend version of above
2284 (define_insn "*subsi3_uxtw"
2285   [(set (match_operand:DI 0 "register_operand" "=rk")
2286         (zero_extend:DI
2287          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2288                    (match_operand:SI 2 "register_operand" "r"))))]
2289   ""
2290   "sub\\t%w0, %w1, %w2"
2291   [(set_attr "type" "alu_sreg")]
2294 (define_insn "subdi3"
2295   [(set (match_operand:DI 0 "register_operand" "=rk,w")
2296         (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2297                   (match_operand:DI 2 "register_operand" "r,w")))]
2298   ""
2299   "@
2300    sub\\t%x0, %x1, %x2
2301    sub\\t%d0, %d1, %d2"
2302   [(set_attr "type" "alu_sreg, neon_sub")
2303    (set_attr "simd" "*,yes")]
2306 (define_expand "subti3"
2307   [(set (match_operand:TI 0 "register_operand" "")
2308         (minus:TI (match_operand:TI 1 "register_operand" "")
2309                   (match_operand:TI 2 "register_operand" "")))]
2310   ""
2312   rtx low = gen_reg_rtx (DImode);
2313   emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2314                                   gen_lowpart (DImode, operands[2])));
2316   rtx high = gen_reg_rtx (DImode);
2317   emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2318                                  gen_highpart (DImode, operands[2])));
2320   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2321   emit_move_insn (gen_highpart (DImode, operands[0]), high);
2322   DONE;
2325 (define_insn "*sub<mode>3_compare0"
2326   [(set (reg:CC_NZ CC_REGNUM)
2327         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2328                                   (match_operand:GPI 2 "register_operand" "r"))
2329                        (const_int 0)))
2330    (set (match_operand:GPI 0 "register_operand" "=r")
2331         (minus:GPI (match_dup 1) (match_dup 2)))]
2332   ""
2333   "subs\\t%<w>0, %<w>1, %<w>2"
2334   [(set_attr "type" "alus_sreg")]
2337 ;; zero_extend version of above
2338 (define_insn "*subsi3_compare0_uxtw"
2339   [(set (reg:CC_NZ CC_REGNUM)
2340         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2341                                  (match_operand:SI 2 "register_operand" "r"))
2342                        (const_int 0)))
2343    (set (match_operand:DI 0 "register_operand" "=r")
2344         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2345   ""
2346   "subs\\t%w0, %w1, %w2"
2347   [(set_attr "type" "alus_sreg")]
2350 (define_insn "sub<mode>3_compare1"
2351   [(set (reg:CC CC_REGNUM)
2352         (compare:CC
2353           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2354           (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2355    (set (match_operand:GPI 0 "register_operand" "=r")
2356         (minus:GPI (match_dup 1) (match_dup 2)))]
2357   ""
2358   "subs\\t%<w>0, %<w>1, %<w>2"
2359   [(set_attr "type" "alus_sreg")]
2362 (define_insn "sub<mode>3_compare1_imm"
2363   [(set (reg:CC CC_REGNUM)
2364         (compare:CC
2365           (match_operand:GPI 1 "register_operand" "r")
2366           (match_operand:GPI 3 "const_int_operand" "n")))
2367    (set (match_operand:GPI 0 "register_operand" "=r")
2368         (plus:GPI (match_dup 1)
2369                   (match_operand:GPI 2 "aarch64_sub_immediate" "J")))]
2370   "INTVAL (operands[3]) == -INTVAL (operands[2])"
2371   "subs\\t%<w>0, %<w>1, #%n2"
2372   [(set_attr "type" "alus_sreg")]
2375 (define_peephole2
2376   [(set (match_operand:GPI 0 "register_operand")
2377         (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
2378                     (match_operand:GPI 2 "aarch64_reg_or_zero")))
2379    (set (reg:CC CC_REGNUM)
2380         (compare:CC
2381           (match_dup 1)
2382           (match_dup 2)))]
2383   "!reg_overlap_mentioned_p (operands[0], operands[1])
2384    && !reg_overlap_mentioned_p (operands[0], operands[2])"
2385   [(const_int 0)]
2386   {
2387     emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
2388                                          operands[2]));
2389     DONE;
2390   }
2393 ;; Same as the above peephole but with the compare and minus in
2394 ;; swapped order.  The restriction on overlap between operand 0
2395 ;; and operands 1 and 2 doesn't apply here.
2396 (define_peephole2
2397   [(set (reg:CC CC_REGNUM)
2398         (compare:CC
2399           (match_operand:GPI 1 "aarch64_reg_or_zero")
2400           (match_operand:GPI 2 "aarch64_reg_or_zero")))
2401    (set (match_operand:GPI 0 "register_operand")
2402         (minus:GPI (match_dup 1)
2403                    (match_dup 2)))]
2404   ""
2405   [(const_int 0)]
2406   {
2407     emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
2408                                          operands[2]));
2409     DONE;
2410   }
2413 (define_peephole2
2414   [(set (match_operand:GPI 0 "register_operand")
2415         (plus:GPI (match_operand:GPI 1 "register_operand")
2416                   (match_operand:GPI 2 "aarch64_sub_immediate")))
2417    (set (reg:CC CC_REGNUM)
2418         (compare:CC
2419           (match_dup 1)
2420           (match_operand:GPI 3 "const_int_operand")))]
2421   "!reg_overlap_mentioned_p (operands[0], operands[1])
2422    && INTVAL (operands[3]) == -INTVAL (operands[2])"
2423   [(const_int 0)]
2424   {
2425     emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
2426                                          operands[2], operands[3]));
2427     DONE;
2428   }
2431 ;; Same as the above peephole but with the compare and minus in
2432 ;; swapped order.  The restriction on overlap between operand 0
2433 ;; and operands 1 doesn't apply here.
2434 (define_peephole2
2435   [(set (reg:CC CC_REGNUM)
2436         (compare:CC
2437           (match_operand:GPI 1 "register_operand")
2438           (match_operand:GPI 3 "const_int_operand")))
2439    (set (match_operand:GPI 0 "register_operand")
2440         (plus:GPI (match_dup 1)
2441                   (match_operand:GPI 2 "aarch64_sub_immediate")))]
2442   "INTVAL (operands[3]) == -INTVAL (operands[2])"
2443   [(const_int 0)]
2444   {
2445     emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
2446                                          operands[2], operands[3]));
2447     DONE;
2448   }
2451 (define_insn "*sub_<shift>_<mode>"
2452   [(set (match_operand:GPI 0 "register_operand" "=r")
2453         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2454                    (ASHIFT:GPI
2455                     (match_operand:GPI 1 "register_operand" "r")
2456                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2457   ""
2458   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2459   [(set_attr "type" "alu_shift_imm")]
2462 ;; zero_extend version of above
2463 (define_insn "*sub_<shift>_si_uxtw"
2464   [(set (match_operand:DI 0 "register_operand" "=r")
2465         (zero_extend:DI
2466          (minus:SI (match_operand:SI 3 "register_operand" "r")
2467                    (ASHIFT:SI
2468                     (match_operand:SI 1 "register_operand" "r")
2469                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2470   ""
2471   "sub\\t%w0, %w3, %w1, <shift> %2"
2472   [(set_attr "type" "alu_shift_imm")]
2475 (define_insn "*sub_mul_imm_<mode>"
2476   [(set (match_operand:GPI 0 "register_operand" "=r")
2477         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2478                    (mult:GPI
2479                     (match_operand:GPI 1 "register_operand" "r")
2480                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2481   ""
2482   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2483   [(set_attr "type" "alu_shift_imm")]
2486 ;; zero_extend version of above
2487 (define_insn "*sub_mul_imm_si_uxtw"
2488   [(set (match_operand:DI 0 "register_operand" "=r")
2489         (zero_extend:DI
2490          (minus:SI (match_operand:SI 3 "register_operand" "r")
2491                    (mult:SI
2492                     (match_operand:SI 1 "register_operand" "r")
2493                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2494   ""
2495   "sub\\t%w0, %w3, %w1, lsl %p2"
2496   [(set_attr "type" "alu_shift_imm")]
2499 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2500   [(set (match_operand:GPI 0 "register_operand" "=rk")
2501         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2502                    (ANY_EXTEND:GPI
2503                     (match_operand:ALLX 2 "register_operand" "r"))))]
2504   ""
2505   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2506   [(set_attr "type" "alu_ext")]
2509 ;; zero_extend version of above
2510 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2511   [(set (match_operand:DI 0 "register_operand" "=rk")
2512         (zero_extend:DI
2513          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2514                    (ANY_EXTEND:SI
2515                     (match_operand:SHORT 2 "register_operand" "r")))))]
2516   ""
2517   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2518   [(set_attr "type" "alu_ext")]
2521 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2522   [(set (match_operand:GPI 0 "register_operand" "=rk")
2523         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2524                    (ashift:GPI (ANY_EXTEND:GPI
2525                                 (match_operand:ALLX 2 "register_operand" "r"))
2526                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
2527   ""
2528   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2529   [(set_attr "type" "alu_ext")]
2532 ;; zero_extend version of above
2533 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2534   [(set (match_operand:DI 0 "register_operand" "=rk")
2535         (zero_extend:DI
2536          (minus:SI (match_operand:SI 1 "register_operand" "rk")
2537                    (ashift:SI (ANY_EXTEND:SI
2538                                (match_operand:SHORT 2 "register_operand" "r"))
2539                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
2540   ""
2541   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2542   [(set_attr "type" "alu_ext")]
2545 (define_insn "*sub_<optab><mode>_multp2"
2546   [(set (match_operand:GPI 0 "register_operand" "=rk")
2547         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2548                    (ANY_EXTRACT:GPI
2549                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2550                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2551                     (match_operand 3 "const_int_operand" "n")
2552                     (const_int 0))))]
2553   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2554   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2555   [(set_attr "type" "alu_ext")]
2558 ;; zero_extend version of above
2559 (define_insn "*sub_<optab>si_multp2_uxtw"
2560   [(set (match_operand:DI 0 "register_operand" "=rk")
2561         (zero_extend:DI
2562          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2563                    (ANY_EXTRACT:SI
2564                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2565                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2566                     (match_operand 3 "const_int_operand" "n")
2567                     (const_int 0)))))]
2568   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2569   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2570   [(set_attr "type" "alu_ext")]
2573 ;; The hardware description is op1 + ~op2 + C.
2574 ;;                           = op1 + (-op2 + 1) + (1 - !C)
2575 ;;                           = op1 - op2 - 1 + 1 - !C
2576 ;;                           = op1 - op2 - !C.
2577 ;; We describe the latter.
2579 (define_insn "*sub<mode>3_carryin0"
2580   [(set (match_operand:GPI 0 "register_operand" "=r")
2581         (minus:GPI
2582           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2583           (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2584    ""
2585    "sbc\\t%<w>0, %<w>1, <w>zr"
2586   [(set_attr "type" "adc_reg")]
2589 ;; zero_extend version of the above
2590 (define_insn "*subsi3_carryin_uxtw"
2591   [(set (match_operand:DI 0 "register_operand" "=r")
2592         (zero_extend:DI
2593           (minus:SI
2594             (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2595             (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2596    ""
2597    "sbc\\t%w0, %w1, wzr"
2598   [(set_attr "type" "adc_reg")]
2601 (define_expand "sub<mode>3_carryin"
2602   [(set (match_operand:GPI 0 "register_operand")
2603         (minus:GPI
2604           (minus:GPI
2605             (match_operand:GPI 1 "aarch64_reg_or_zero")
2606             (match_operand:GPI 2 "register_operand"))
2607           (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2608    ""
2609    ""
2612 (define_insn "*sub<mode>3_carryin"
2613   [(set (match_operand:GPI 0 "register_operand" "=r")
2614         (minus:GPI
2615           (minus:GPI
2616             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2617             (match_operand:GPI 2 "register_operand" "r"))
2618           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2620    ""
2621    "sbc\\t%<w>0, %<w>1, %<w>2"
2622   [(set_attr "type" "adc_reg")]
2625 ;; zero_extend version of the above
2626 (define_insn "*subsi3_carryin_uxtw"
2627   [(set (match_operand:DI 0 "register_operand" "=r")
2628         (zero_extend:DI
2629           (minus:SI
2630             (minus:SI
2631               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2632               (match_operand:SI 2 "register_operand" "r"))
2633             (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2635    ""
2636    "sbc\\t%w0, %w1, %w2"
2637   [(set_attr "type" "adc_reg")]
2640 (define_insn "*sub<mode>3_carryin_alt"
2641   [(set (match_operand:GPI 0 "register_operand" "=r")
2642         (minus:GPI
2643           (minus:GPI
2644             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2645             (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2646           (match_operand:GPI 2 "register_operand" "r")))]
2647    ""
2648    "sbc\\t%<w>0, %<w>1, %<w>2"
2649   [(set_attr "type" "adc_reg")]
2652 ;; zero_extend version of the above
2653 (define_insn "*subsi3_carryin_alt_uxtw"
2654   [(set (match_operand:DI 0 "register_operand" "=r")
2655         (zero_extend:DI
2656           (minus:SI
2657             (minus:SI
2658               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2659               (match_operand:SI 3 "aarch64_borrow_operation" ""))
2660             (match_operand:SI 2 "register_operand" "r"))))]
2661    ""
2662    "sbc\\t%w0, %w1, %w2"
2663   [(set_attr "type" "adc_reg")]
2666 (define_insn "*sub_uxt<mode>_shift2"
2667   [(set (match_operand:GPI 0 "register_operand" "=rk")
2668         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2669                    (and:GPI
2670                     (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2671                                 (match_operand 2 "aarch64_imm3" "Ui3"))
2672                     (match_operand 3 "const_int_operand" "n"))))]
2673   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2674   "*
2675   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2676                                            INTVAL (operands[3])));
2677   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2678   [(set_attr "type" "alu_ext")]
2681 ;; zero_extend version of above
2682 (define_insn "*sub_uxtsi_shift2_uxtw"
2683   [(set (match_operand:DI 0 "register_operand" "=rk")
2684         (zero_extend:DI
2685          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2686                    (and:SI
2687                     (ashift:SI (match_operand:SI 1 "register_operand" "r")
2688                                (match_operand 2 "aarch64_imm3" "Ui3"))
2689                     (match_operand 3 "const_int_operand" "n")))))]
2690   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2691   "*
2692   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2693                                            INTVAL (operands[3])));
2694   return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2695   [(set_attr "type" "alu_ext")]
2698 (define_insn "*sub_uxt<mode>_multp2"
2699   [(set (match_operand:GPI 0 "register_operand" "=rk")
2700         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2701                    (and:GPI
2702                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2703                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2704                     (match_operand 3 "const_int_operand" "n"))))]
2705   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2706   "*
2707   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2708                                            INTVAL (operands[3])));
2709   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2710   [(set_attr "type" "alu_ext")]
2713 ;; zero_extend version of above
2714 (define_insn "*sub_uxtsi_multp2_uxtw"
2715   [(set (match_operand:DI 0 "register_operand" "=rk")
2716         (zero_extend:DI
2717          (minus:SI (match_operand:SI 4 "register_operand" "rk")
2718                    (and:SI
2719                     (mult:SI (match_operand:SI 1 "register_operand" "r")
2720                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2721                     (match_operand 3 "const_int_operand" "n")))))]
2722   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2723   "*
2724   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2725                                            INTVAL (operands[3])));
2726   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2727   [(set_attr "type" "alu_ext")]
2730 (define_expand "abs<mode>2"
2731   [(match_operand:GPI 0 "register_operand" "")
2732    (match_operand:GPI 1 "register_operand" "")]
2733   ""
2734   {
2735     rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2736     rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2737     emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2738     DONE;
2739   }
2742 (define_insn "neg<mode>2"
2743   [(set (match_operand:GPI 0 "register_operand" "=r,w")
2744         (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2745   ""
2746   "@
2747    neg\\t%<w>0, %<w>1
2748    neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2749   [(set_attr "type" "alu_sreg, neon_neg<q>")
2750    (set_attr "simd" "*,yes")]
2753 ;; zero_extend version of above
2754 (define_insn "*negsi2_uxtw"
2755   [(set (match_operand:DI 0 "register_operand" "=r")
2756         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2757   ""
2758   "neg\\t%w0, %w1"
2759   [(set_attr "type" "alu_sreg")]
2762 (define_insn "*ngc<mode>"
2763   [(set (match_operand:GPI 0 "register_operand" "=r")
2764         (minus:GPI
2765           (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2766           (match_operand:GPI 1 "register_operand" "r")))]
2767   ""
2768   "ngc\\t%<w>0, %<w>1"
2769   [(set_attr "type" "adc_reg")]
2772 (define_insn "*ngcsi_uxtw"
2773   [(set (match_operand:DI 0 "register_operand" "=r")
2774         (zero_extend:DI
2775           (minus:SI
2776             (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2777             (match_operand:SI 1 "register_operand" "r"))))]
2778   ""
2779   "ngc\\t%w0, %w1"
2780   [(set_attr "type" "adc_reg")]
2783 (define_insn "neg<mode>2_compare0"
2784   [(set (reg:CC_NZ CC_REGNUM)
2785         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2786                        (const_int 0)))
2787    (set (match_operand:GPI 0 "register_operand" "=r")
2788         (neg:GPI (match_dup 1)))]
2789   ""
2790   "negs\\t%<w>0, %<w>1"
2791   [(set_attr "type" "alus_sreg")]
2794 ;; zero_extend version of above
2795 (define_insn "*negsi2_compare0_uxtw"
2796   [(set (reg:CC_NZ CC_REGNUM)
2797         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2798                        (const_int 0)))
2799    (set (match_operand:DI 0 "register_operand" "=r")
2800         (zero_extend:DI (neg:SI (match_dup 1))))]
2801   ""
2802   "negs\\t%w0, %w1"
2803   [(set_attr "type" "alus_sreg")]
2806 (define_insn "*neg_<shift><mode>3_compare0"
2807   [(set (reg:CC_NZ CC_REGNUM)
2808         (compare:CC_NZ
2809          (neg:GPI (ASHIFT:GPI
2810                    (match_operand:GPI 1 "register_operand" "r")
2811                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2812          (const_int 0)))
2813    (set (match_operand:GPI 0 "register_operand" "=r")
2814         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2815   ""
2816   "negs\\t%<w>0, %<w>1, <shift> %2"
2817   [(set_attr "type" "alus_shift_imm")]
2820 (define_insn "*neg_<shift>_<mode>2"
2821   [(set (match_operand:GPI 0 "register_operand" "=r")
2822         (neg:GPI (ASHIFT:GPI
2823                   (match_operand:GPI 1 "register_operand" "r")
2824                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2825   ""
2826   "neg\\t%<w>0, %<w>1, <shift> %2"
2827   [(set_attr "type" "alu_shift_imm")]
2830 ;; zero_extend version of above
2831 (define_insn "*neg_<shift>_si2_uxtw"
2832   [(set (match_operand:DI 0 "register_operand" "=r")
2833         (zero_extend:DI
2834          (neg:SI (ASHIFT:SI
2835                   (match_operand:SI 1 "register_operand" "r")
2836                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2837   ""
2838   "neg\\t%w0, %w1, <shift> %2"
2839   [(set_attr "type" "alu_shift_imm")]
2842 (define_insn "*neg_mul_imm_<mode>2"
2843   [(set (match_operand:GPI 0 "register_operand" "=r")
2844         (neg:GPI (mult:GPI
2845                   (match_operand:GPI 1 "register_operand" "r")
2846                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2847   ""
2848   "neg\\t%<w>0, %<w>1, lsl %p2"
2849   [(set_attr "type" "alu_shift_imm")]
2852 ;; zero_extend version of above
2853 (define_insn "*neg_mul_imm_si2_uxtw"
2854   [(set (match_operand:DI 0 "register_operand" "=r")
2855         (zero_extend:DI
2856          (neg:SI (mult:SI
2857                   (match_operand:SI 1 "register_operand" "r")
2858                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2859   ""
2860   "neg\\t%w0, %w1, lsl %p2"
2861   [(set_attr "type" "alu_shift_imm")]
2864 (define_insn "mul<mode>3"
2865   [(set (match_operand:GPI 0 "register_operand" "=r")
2866         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2867                   (match_operand:GPI 2 "register_operand" "r")))]
2868   ""
2869   "mul\\t%<w>0, %<w>1, %<w>2"
2870   [(set_attr "type" "mul")]
2873 ;; zero_extend version of above
2874 (define_insn "*mulsi3_uxtw"
2875   [(set (match_operand:DI 0 "register_operand" "=r")
2876         (zero_extend:DI
2877          (mult:SI (match_operand:SI 1 "register_operand" "r")
2878                   (match_operand:SI 2 "register_operand" "r"))))]
2879   ""
2880   "mul\\t%w0, %w1, %w2"
2881   [(set_attr "type" "mul")]
2884 (define_insn "madd<mode>"
2885   [(set (match_operand:GPI 0 "register_operand" "=r")
2886         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2887                             (match_operand:GPI 2 "register_operand" "r"))
2888                   (match_operand:GPI 3 "register_operand" "r")))]
2889   ""
2890   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2891   [(set_attr "type" "mla")]
2894 ;; zero_extend version of above
2895 (define_insn "*maddsi_uxtw"
2896   [(set (match_operand:DI 0 "register_operand" "=r")
2897         (zero_extend:DI
2898          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2899                            (match_operand:SI 2 "register_operand" "r"))
2900                   (match_operand:SI 3 "register_operand" "r"))))]
2901   ""
2902   "madd\\t%w0, %w1, %w2, %w3"
2903   [(set_attr "type" "mla")]
2906 (define_insn "*msub<mode>"
2907   [(set (match_operand:GPI 0 "register_operand" "=r")
2908         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2909                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2910                              (match_operand:GPI 2 "register_operand" "r"))))]
2912   ""
2913   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2914   [(set_attr "type" "mla")]
2917 ;; zero_extend version of above
2918 (define_insn "*msubsi_uxtw"
2919   [(set (match_operand:DI 0 "register_operand" "=r")
2920         (zero_extend:DI
2921          (minus:SI (match_operand:SI 3 "register_operand" "r")
2922                    (mult:SI (match_operand:SI 1 "register_operand" "r")
2923                             (match_operand:SI 2 "register_operand" "r")))))]
2925   ""
2926   "msub\\t%w0, %w1, %w2, %w3"
2927   [(set_attr "type" "mla")]
2930 (define_insn "*mul<mode>_neg"
2931   [(set (match_operand:GPI 0 "register_operand" "=r")
2932         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2933                   (match_operand:GPI 2 "register_operand" "r")))]
2935   ""
2936   "mneg\\t%<w>0, %<w>1, %<w>2"
2937   [(set_attr "type" "mul")]
2940 ;; zero_extend version of above
2941 (define_insn "*mulsi_neg_uxtw"
2942   [(set (match_operand:DI 0 "register_operand" "=r")
2943         (zero_extend:DI
2944          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2945                   (match_operand:SI 2 "register_operand" "r"))))]
2947   ""
2948   "mneg\\t%w0, %w1, %w2"
2949   [(set_attr "type" "mul")]
2952 (define_insn "<su_optab>mulsidi3"
2953   [(set (match_operand:DI 0 "register_operand" "=r")
2954         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2955                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2956   ""
2957   "<su>mull\\t%0, %w1, %w2"
2958   [(set_attr "type" "<su>mull")]
2961 (define_insn "<su_optab>maddsidi4"
2962   [(set (match_operand:DI 0 "register_operand" "=r")
2963         (plus:DI (mult:DI
2964                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2965                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2966                  (match_operand:DI 3 "register_operand" "r")))]
2967   ""
2968   "<su>maddl\\t%0, %w1, %w2, %3"
2969   [(set_attr "type" "<su>mlal")]
2972 (define_insn "<su_optab>msubsidi4"
2973   [(set (match_operand:DI 0 "register_operand" "=r")
2974         (minus:DI
2975          (match_operand:DI 3 "register_operand" "r")
2976          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2977                   (ANY_EXTEND:DI
2978                    (match_operand:SI 2 "register_operand" "r")))))]
2979   ""
2980   "<su>msubl\\t%0, %w1, %w2, %3"
2981   [(set_attr "type" "<su>mlal")]
2984 (define_insn "*<su_optab>mulsidi_neg"
2985   [(set (match_operand:DI 0 "register_operand" "=r")
2986         (mult:DI (neg:DI
2987                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2988                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2989   ""
2990   "<su>mnegl\\t%0, %w1, %w2"
2991   [(set_attr "type" "<su>mull")]
2994 (define_expand "<su_optab>mulditi3"
2995   [(set (match_operand:TI 0 "register_operand")
2996         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2997                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
2998   ""
3000   rtx low = gen_reg_rtx (DImode);
3001   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
3003   rtx high = gen_reg_rtx (DImode);
3004   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
3006   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
3007   emit_move_insn (gen_highpart (DImode, operands[0]), high);
3008   DONE;
3011 ;; The default expansion of multi3 using umuldi3_highpart will perform
3012 ;; the additions in an order that fails to combine into two madd insns.
3013 (define_expand "multi3"
3014   [(set (match_operand:TI 0 "register_operand")
3015         (mult:TI (match_operand:TI 1 "register_operand")
3016                  (match_operand:TI 2 "register_operand")))]
3017   ""
3019   rtx l0 = gen_reg_rtx (DImode);
3020   rtx l1 = gen_lowpart (DImode, operands[1]);
3021   rtx l2 = gen_lowpart (DImode, operands[2]);
3022   rtx h0 = gen_reg_rtx (DImode);
3023   rtx h1 = gen_highpart (DImode, operands[1]);
3024   rtx h2 = gen_highpart (DImode, operands[2]);
3026   emit_insn (gen_muldi3 (l0, l1, l2));
3027   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3028   emit_insn (gen_madddi (h0, h1, l2, h0));
3029   emit_insn (gen_madddi (h0, l1, h2, h0));
3031   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
3032   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
3033   DONE;
3036 (define_insn "<su>muldi3_highpart"
3037   [(set (match_operand:DI 0 "register_operand" "=r")
3038         (truncate:DI
3039          (lshiftrt:TI
3040           (mult:TI
3041            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
3042            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
3043           (const_int 64))))]
3044   ""
3045   "<su>mulh\\t%0, %1, %2"
3046   [(set_attr "type" "<su>mull")]
3049 (define_insn "<su_optab>div<mode>3"
3050   [(set (match_operand:GPI 0 "register_operand" "=r")
3051         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
3052                      (match_operand:GPI 2 "register_operand" "r")))]
3053   ""
3054   "<su>div\\t%<w>0, %<w>1, %<w>2"
3055   [(set_attr "type" "<su>div")]
3058 ;; zero_extend version of above
3059 (define_insn "*<su_optab>divsi3_uxtw"
3060   [(set (match_operand:DI 0 "register_operand" "=r")
3061         (zero_extend:DI
3062          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
3063                      (match_operand:SI 2 "register_operand" "r"))))]
3064   ""
3065   "<su>div\\t%w0, %w1, %w2"
3066   [(set_attr "type" "<su>div")]
3069 ;; -------------------------------------------------------------------
3070 ;; Comparison insns
3071 ;; -------------------------------------------------------------------
3073 (define_insn "cmp<mode>"
3074   [(set (reg:CC CC_REGNUM)
3075         (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
3076                     (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
3077   ""
3078   "@
3079    cmp\\t%<w>0, %<w>1
3080    cmp\\t%<w>0, %1
3081    cmn\\t%<w>0, #%n1"
3082   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3085 (define_insn "fcmp<mode>"
3086   [(set (reg:CCFP CC_REGNUM)
3087         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
3088                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3089    "TARGET_FLOAT"
3090    "@
3091     fcmp\\t%<s>0, #0.0
3092     fcmp\\t%<s>0, %<s>1"
3093   [(set_attr "type" "fcmp<s>")]
3096 (define_insn "fcmpe<mode>"
3097   [(set (reg:CCFPE CC_REGNUM)
3098         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
3099                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3100    "TARGET_FLOAT"
3101    "@
3102     fcmpe\\t%<s>0, #0.0
3103     fcmpe\\t%<s>0, %<s>1"
3104   [(set_attr "type" "fcmp<s>")]
3107 (define_insn "*cmp_swp_<shift>_reg<mode>"
3108   [(set (reg:CC_SWP CC_REGNUM)
3109         (compare:CC_SWP (ASHIFT:GPI
3110                          (match_operand:GPI 0 "register_operand" "r")
3111                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3112                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3113   ""
3114   "cmp\\t%<w>2, %<w>0, <shift> %1"
3115   [(set_attr "type" "alus_shift_imm")]
3118 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3119   [(set (reg:CC_SWP CC_REGNUM)
3120         (compare:CC_SWP (ANY_EXTEND:GPI
3121                          (match_operand:ALLX 0 "register_operand" "r"))
3122                         (match_operand:GPI 1 "register_operand" "r")))]
3123   ""
3124   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3125   [(set_attr "type" "alus_ext")]
3128 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3129   [(set (reg:CC_SWP CC_REGNUM)
3130         (compare:CC_SWP (ashift:GPI
3131                          (ANY_EXTEND:GPI
3132                           (match_operand:ALLX 0 "register_operand" "r"))
3133                          (match_operand 1 "aarch64_imm3" "Ui3"))
3134         (match_operand:GPI 2 "register_operand" "r")))]
3135   ""
3136   "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3137   [(set_attr "type" "alus_ext")]
3140 ;; -------------------------------------------------------------------
3141 ;; Store-flag and conditional select insns
3142 ;; -------------------------------------------------------------------
3144 (define_expand "cstore<mode>4"
3145   [(set (match_operand:SI 0 "register_operand" "")
3146         (match_operator:SI 1 "aarch64_comparison_operator"
3147          [(match_operand:GPI 2 "register_operand" "")
3148           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3149   ""
3150   "
3151   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3152                                       operands[3]);
3153   operands[3] = const0_rtx;
3154   "
3157 (define_expand "cstorecc4"
3158   [(set (match_operand:SI 0 "register_operand")
3159        (match_operator 1 "aarch64_comparison_operator_mode"
3160         [(match_operand 2 "cc_register")
3161          (match_operand 3 "const0_operand")]))]
3162   ""
3164   emit_insn (gen_rtx_SET (operands[0], operands[1]));
3165   DONE;
3169 (define_expand "cstore<mode>4"
3170   [(set (match_operand:SI 0 "register_operand" "")
3171         (match_operator:SI 1 "aarch64_comparison_operator_mode"
3172          [(match_operand:GPF 2 "register_operand" "")
3173           (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3174   ""
3175   "
3176   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3177                                       operands[3]);
3178   operands[3] = const0_rtx;
3179   "
3182 (define_insn "aarch64_cstore<mode>"
3183   [(set (match_operand:ALLI 0 "register_operand" "=r")
3184         (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3185          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3186   ""
3187   "cset\\t%<w>0, %m1"
3188   [(set_attr "type" "csel")]
3191 ;; For a 24-bit immediate CST we can optimize the compare for equality
3192 ;; and branch sequence from:
3193 ;;      mov     x0, #imm1
3194 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
3195 ;;      cmp     x1, x0
3196 ;;      cset    x2, <ne,eq>
3197 ;; into the shorter:
3198 ;;      sub     x0, x1, #(CST & 0xfff000)
3199 ;;      subs    x0, x0, #(CST & 0x000fff)
3200 ;;      cset x2, <ne, eq>.
3201 (define_insn_and_split "*compare_cstore<mode>_insn"
3202   [(set (match_operand:GPI 0 "register_operand" "=r")
3203          (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3204                   (match_operand:GPI 2 "aarch64_imm24" "n")))
3205    (clobber (reg:CC CC_REGNUM))]
3206   "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3207    && !aarch64_plus_operand (operands[2], <MODE>mode)
3208    && !reload_completed"
3209   "#"
3210   "&& true"
3211   [(const_int 0)]
3212   {
3213     HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3214     HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3215     rtx tmp = gen_reg_rtx (<MODE>mode);
3216     emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3217     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3218     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3219     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3220     emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3221     DONE;
3222   }
3223   [(set_attr "type" "csel")]
3226 ;; zero_extend version of the above
3227 (define_insn "*cstoresi_insn_uxtw"
3228   [(set (match_operand:DI 0 "register_operand" "=r")
3229         (zero_extend:DI
3230          (match_operator:SI 1 "aarch64_comparison_operator_mode"
3231           [(match_operand 2 "cc_register" "") (const_int 0)])))]
3232   ""
3233   "cset\\t%w0, %m1"
3234   [(set_attr "type" "csel")]
3237 (define_insn "cstore<mode>_neg"
3238   [(set (match_operand:ALLI 0 "register_operand" "=r")
3239         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3240                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
3241   ""
3242   "csetm\\t%<w>0, %m1"
3243   [(set_attr "type" "csel")]
3246 ;; zero_extend version of the above
3247 (define_insn "*cstoresi_neg_uxtw"
3248   [(set (match_operand:DI 0 "register_operand" "=r")
3249         (zero_extend:DI
3250          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3251                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3252   ""
3253   "csetm\\t%w0, %m1"
3254   [(set_attr "type" "csel")]
3257 (define_expand "cmov<mode>6"
3258   [(set (match_operand:GPI 0 "register_operand" "")
3259         (if_then_else:GPI
3260          (match_operator 1 "aarch64_comparison_operator"
3261           [(match_operand:GPI 2 "register_operand" "")
3262            (match_operand:GPI 3 "aarch64_plus_operand" "")])
3263          (match_operand:GPI 4 "register_operand" "")
3264          (match_operand:GPI 5 "register_operand" "")))]
3265   ""
3266   "
3267   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3268                                       operands[3]);
3269   operands[3] = const0_rtx;
3270   "
3273 (define_expand "cmov<mode>6"
3274   [(set (match_operand:GPF 0 "register_operand" "")
3275         (if_then_else:GPF
3276          (match_operator 1 "aarch64_comparison_operator"
3277           [(match_operand:GPF 2 "register_operand" "")
3278            (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3279          (match_operand:GPF 4 "register_operand" "")
3280          (match_operand:GPF 5 "register_operand" "")))]
3281   ""
3282   "
3283   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3284                                       operands[3]);
3285   operands[3] = const0_rtx;
3286   "
3289 (define_insn "*cmov<mode>_insn"
3290   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3291         (if_then_else:ALLI
3292          (match_operator 1 "aarch64_comparison_operator"
3293           [(match_operand 2 "cc_register" "") (const_int 0)])
3294          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3295          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3296   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3297      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3298   ;; Final two alternatives should be unreachable, but included for completeness
3299   "@
3300    csel\\t%<w>0, %<w>3, %<w>4, %m1
3301    csinv\\t%<w>0, %<w>3, <w>zr, %m1
3302    csinv\\t%<w>0, %<w>4, <w>zr, %M1
3303    csinc\\t%<w>0, %<w>3, <w>zr, %m1
3304    csinc\\t%<w>0, %<w>4, <w>zr, %M1
3305    mov\\t%<w>0, -1
3306    mov\\t%<w>0, 1"
3307   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3310 ;; zero_extend version of above
3311 (define_insn "*cmovsi_insn_uxtw"
3312   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3313         (zero_extend:DI
3314          (if_then_else:SI
3315           (match_operator 1 "aarch64_comparison_operator"
3316            [(match_operand 2 "cc_register" "") (const_int 0)])
3317           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3318           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3319   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3320      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3321   ;; Final two alternatives should be unreachable, but included for completeness
3322   "@
3323    csel\\t%w0, %w3, %w4, %m1
3324    csinv\\t%w0, %w3, wzr, %m1
3325    csinv\\t%w0, %w4, wzr, %M1
3326    csinc\\t%w0, %w3, wzr, %m1
3327    csinc\\t%w0, %w4, wzr, %M1
3328    mov\\t%w0, -1
3329    mov\\t%w0, 1"
3330   [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3333 (define_insn "*cmovdi_insn_uxtw"
3334   [(set (match_operand:DI 0 "register_operand" "=r")
3335         (if_then_else:DI
3336          (match_operator 1 "aarch64_comparison_operator"
3337           [(match_operand 2 "cc_register" "") (const_int 0)])
3338          (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3339          (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3340   ""
3341   "csel\\t%w0, %w3, %w4, %m1"
3342   [(set_attr "type" "csel")]
3345 (define_insn "*cmov<mode>_insn"
3346   [(set (match_operand:GPF 0 "register_operand" "=w")
3347         (if_then_else:GPF
3348          (match_operator 1 "aarch64_comparison_operator"
3349           [(match_operand 2 "cc_register" "") (const_int 0)])
3350          (match_operand:GPF 3 "register_operand" "w")
3351          (match_operand:GPF 4 "register_operand" "w")))]
3352   "TARGET_FLOAT"
3353   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3354   [(set_attr "type" "fcsel")]
3357 (define_expand "mov<mode>cc"
3358   [(set (match_operand:ALLI 0 "register_operand" "")
3359         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3360                            (match_operand:ALLI 2 "register_operand" "")
3361                            (match_operand:ALLI 3 "register_operand" "")))]
3362   ""
3363   {
3364     rtx ccreg;
3365     enum rtx_code code = GET_CODE (operands[1]);
3367     if (code == UNEQ || code == LTGT)
3368       FAIL;
3370     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3371                                      XEXP (operands[1], 1));
3372     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3373   }
3376 (define_expand "mov<GPF:mode><GPI:mode>cc"
3377   [(set (match_operand:GPI 0 "register_operand" "")
3378         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3379                           (match_operand:GPF 2 "register_operand" "")
3380                           (match_operand:GPF 3 "register_operand" "")))]
3381   ""
3382   {
3383     rtx ccreg;
3384     enum rtx_code code = GET_CODE (operands[1]);
3386     if (code == UNEQ || code == LTGT)
3387       FAIL;
3389     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3390                                   XEXP (operands[1], 1));
3391     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3392   }
3395 (define_expand "mov<mode>cc"
3396   [(set (match_operand:GPF 0 "register_operand" "")
3397         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3398                           (match_operand:GPF 2 "register_operand" "")
3399                           (match_operand:GPF 3 "register_operand" "")))]
3400   ""
3401   {
3402     rtx ccreg;
3403     enum rtx_code code = GET_CODE (operands[1]);
3405     if (code == UNEQ || code == LTGT)
3406       FAIL;
3408     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3409                                   XEXP (operands[1], 1));
3410     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3411   }
3414 (define_expand "<neg_not_op><mode>cc"
3415   [(set (match_operand:GPI 0 "register_operand" "")
3416         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3417                           (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3418                           (match_operand:GPI 3 "register_operand" "")))]
3419   ""
3420   {
3421     rtx ccreg;
3422     enum rtx_code code = GET_CODE (operands[1]);
3424     if (code == UNEQ || code == LTGT)
3425       FAIL;
3427     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3428                                       XEXP (operands[1], 1));
3429     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3430   }
3433 ;; CRC32 instructions.
3434 (define_insn "aarch64_<crc_variant>"
3435   [(set (match_operand:SI 0 "register_operand" "=r")
3436         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3437                     (match_operand:<crc_mode> 2 "register_operand" "r")]
3438          CRC))]
3439   "TARGET_CRC32"
3440   {
3441     if (GET_MODE_BITSIZE (<crc_mode>mode) >= 64)
3442       return "<crc_variant>\\t%w0, %w1, %x2";
3443     else
3444       return "<crc_variant>\\t%w0, %w1, %w2";
3445   }
3446   [(set_attr "type" "crc")]
3449 (define_insn "*csinc2<mode>_insn"
3450   [(set (match_operand:GPI 0 "register_operand" "=r")
3451         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3452                   (match_operand:GPI 1 "register_operand" "r")))]
3453   ""
3454   "cinc\\t%<w>0, %<w>1, %m2"
3455   [(set_attr "type" "csel")]
3458 (define_insn "csinc3<mode>_insn"
3459   [(set (match_operand:GPI 0 "register_operand" "=r")
3460         (if_then_else:GPI
3461           (match_operand 1 "aarch64_comparison_operation" "")
3462           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3463                     (const_int 1))
3464           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3465   ""
3466   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3467   [(set_attr "type" "csel")]
3470 (define_insn "*csinv3<mode>_insn"
3471   [(set (match_operand:GPI 0 "register_operand" "=r")
3472         (if_then_else:GPI
3473           (match_operand 1 "aarch64_comparison_operation" "")
3474           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3475           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3476   ""
3477   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3478   [(set_attr "type" "csel")]
3481 (define_insn "csneg3_uxtw_insn"
3482   [(set (match_operand:DI 0 "register_operand" "=r")
3483         (zero_extend:DI
3484           (if_then_else:SI
3485             (match_operand 1 "aarch64_comparison_operation" "")
3486             (neg:SI (match_operand:SI 2 "register_operand" "r"))
3487             (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3488   ""
3489   "csneg\\t%w0, %w3, %w2, %M1"
3490   [(set_attr "type" "csel")]
3493 (define_insn "csneg3<mode>_insn"
3494   [(set (match_operand:GPI 0 "register_operand" "=r")
3495         (if_then_else:GPI
3496           (match_operand 1 "aarch64_comparison_operation" "")
3497           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3498           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3499   ""
3500   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3501   [(set_attr "type" "csel")]
3504 ;; If X can be loaded by a single CNT[BHWD] instruction,
3506 ;;    A = UMAX (B, X)
3508 ;; is equivalent to:
3510 ;;    TMP = UQDEC[BHWD] (B, X)
3511 ;;    A = TMP + X
3513 ;; Defining the pattern this way means that:
3515 ;;    A = UMAX (B, X) - X
3517 ;; becomes:
3519 ;;    TMP1 = UQDEC[BHWD] (B, X)
3520 ;;    TMP2 = TMP1 + X
3521 ;;    A = TMP2 - X
3523 ;; which combine can optimize to:
3525 ;;    A = UQDEC[BHWD] (B, X)
3527 ;; We don't use match_operand predicates because the order of the operands
3528 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
3529 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
3530 (define_expand "umax<mode>3"
3531   [(set (match_operand:GPI 0 "register_operand")
3532         (umax:GPI (match_operand:GPI 1 "")
3533                   (match_operand:GPI 2 "")))]
3534   "TARGET_SVE"
3535   {
3536     if (aarch64_sve_cnt_immediate (operands[1], <MODE>mode))
3537       std::swap (operands[1], operands[2]);
3538     else if (!aarch64_sve_cnt_immediate (operands[2], <MODE>mode))
3539       FAIL;
3540     rtx temp = gen_reg_rtx (<MODE>mode);
3541     operands[1] = force_reg (<MODE>mode, operands[1]);
3542     emit_insn (gen_aarch64_uqdec<mode> (temp, operands[1], operands[2]));
3543     emit_insn (gen_add<mode>3 (operands[0], temp, operands[2]));
3544     DONE;
3545   }
3548 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
3549 (define_insn "aarch64_uqdec<mode>"
3550   [(set (match_operand:GPI 0 "register_operand" "=r")
3551         (minus:GPI
3552          (umax:GPI (match_operand:GPI 1 "register_operand" "0")
3553                    (match_operand:GPI 2 "aarch64_sve_cnt_immediate" "Usv"))
3554          (match_dup 2)))]
3555   "TARGET_SVE"
3556   {
3557     return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>0", operands[2]);
3558   }
3561 ;; -------------------------------------------------------------------
3562 ;; Logical operations
3563 ;; -------------------------------------------------------------------
3566 (define_insn_and_split "*aarch64_and<mode>_imm2"
3567   [(set (match_operand:GPI 0 "register_operand" "=rk")
3568         (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3569                  (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3570   ""
3571   "#"
3572   "true"
3573   [(const_int 0)]
3574   {
3575      HOST_WIDE_INT val = INTVAL (operands[2]);
3576      rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3577      rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3579      emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3580      emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3581      DONE;
3582   }
3585 (define_insn "<optab><mode>3"
3586   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3587         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3588                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3589   ""
3590   "@
3591   <logical>\\t%<w>0, %<w>1, %<w>2
3592   <logical>\\t%<w>0, %<w>1, %2
3593   <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3594   [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3595    (set_attr "simd" "*,*,yes")]
3598 ;; zero_extend version of above
3599 (define_insn "*<optab>si3_uxtw"
3600   [(set (match_operand:DI 0 "register_operand" "=r,rk")
3601         (zero_extend:DI
3602          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3603                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3604   ""
3605   "@
3606    <logical>\\t%w0, %w1, %w2
3607    <logical>\\t%w0, %w1, %2"
3608   [(set_attr "type" "logic_reg,logic_imm")]
3611 (define_insn "*and<mode>3_compare0"
3612   [(set (reg:CC_NZ CC_REGNUM)
3613         (compare:CC_NZ
3614          (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3615                   (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3616          (const_int 0)))
3617    (set (match_operand:GPI 0 "register_operand" "=r,r")
3618         (and:GPI (match_dup 1) (match_dup 2)))]
3619   ""
3620   "@
3621    ands\\t%<w>0, %<w>1, %<w>2
3622    ands\\t%<w>0, %<w>1, %2"
3623   [(set_attr "type" "logics_reg,logics_imm")]
3626 ;; zero_extend version of above
3627 (define_insn "*andsi3_compare0_uxtw"
3628   [(set (reg:CC_NZ CC_REGNUM)
3629         (compare:CC_NZ
3630          (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3631                  (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3632          (const_int 0)))
3633    (set (match_operand:DI 0 "register_operand" "=r,r")
3634         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3635   ""
3636   "@
3637    ands\\t%w0, %w1, %w2
3638    ands\\t%w0, %w1, %2"
3639   [(set_attr "type" "logics_reg,logics_imm")]
3642 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3643   [(set (reg:CC_NZ CC_REGNUM)
3644         (compare:CC_NZ
3645          (and:GPI (SHIFT:GPI
3646                    (match_operand:GPI 1 "register_operand" "r")
3647                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3648                   (match_operand:GPI 3 "register_operand" "r"))
3649          (const_int 0)))
3650    (set (match_operand:GPI 0 "register_operand" "=r")
3651         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3652   ""
3653   "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3654   [(set_attr "type" "logics_shift_imm")]
3657 ;; zero_extend version of above
3658 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3659   [(set (reg:CC_NZ CC_REGNUM)
3660         (compare:CC_NZ
3661          (and:SI (SHIFT:SI
3662                   (match_operand:SI 1 "register_operand" "r")
3663                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3664                  (match_operand:SI 3 "register_operand" "r"))
3665          (const_int 0)))
3666    (set (match_operand:DI 0 "register_operand" "=r")
3667         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3668                                 (match_dup 3))))]
3669   ""
3670   "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3671   [(set_attr "type" "logics_shift_imm")]
3674 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3675   [(set (match_operand:GPI 0 "register_operand" "=r")
3676         (LOGICAL:GPI (SHIFT:GPI
3677                       (match_operand:GPI 1 "register_operand" "r")
3678                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3679                      (match_operand:GPI 3 "register_operand" "r")))]
3680   ""
3681   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3682   [(set_attr "type" "logic_shift_imm")]
3685 (define_insn "*<optab>_rol<mode>3"
3686   [(set (match_operand:GPI 0 "register_operand" "=r")
3687         (LOGICAL:GPI (rotate:GPI
3688                       (match_operand:GPI 1 "register_operand" "r")
3689                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3690                      (match_operand:GPI 3 "register_operand" "r")))]
3691   ""
3692   "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3693   [(set_attr "type" "logic_shift_imm")]
3696 ;; zero_extend versions of above
3697 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3698   [(set (match_operand:DI 0 "register_operand" "=r")
3699         (zero_extend:DI
3700          (LOGICAL:SI (SHIFT:SI
3701                       (match_operand:SI 1 "register_operand" "r")
3702                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3703                      (match_operand:SI 3 "register_operand" "r"))))]
3704   ""
3705   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3706   [(set_attr "type" "logic_shift_imm")]
3709 (define_insn "*<optab>_rolsi3_uxtw"
3710   [(set (match_operand:DI 0 "register_operand" "=r")
3711         (zero_extend:DI
3712          (LOGICAL:SI (rotate:SI
3713                       (match_operand:SI 1 "register_operand" "r")
3714                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3715                      (match_operand:SI 3 "register_operand" "r"))))]
3716   ""
3717   "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3718   [(set_attr "type" "logic_shift_imm")]
3721 (define_insn "one_cmpl<mode>2"
3722   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3723         (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3724   ""
3725   "@
3726   mvn\\t%<w>0, %<w>1
3727   mvn\\t%0.8b, %1.8b"
3728   [(set_attr "type" "logic_reg,neon_logic")
3729    (set_attr "simd" "*,yes")]
3732 (define_insn "*one_cmpl_<optab><mode>2"
3733   [(set (match_operand:GPI 0 "register_operand" "=r")
3734         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3735                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3736   ""
3737   "mvn\\t%<w>0, %<w>1, <shift> %2"
3738   [(set_attr "type" "logic_shift_imm")]
3741 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3743 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3744   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3745         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3746                      (match_operand:GPI 2 "register_operand" "r,w")))]
3747   ""
3748   "@
3749   <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3750   <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3751   [(set_attr "type" "logic_reg,neon_logic")
3752    (set_attr "simd" "*,yes")]
3755 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3756   [(set (match_operand:DI 0 "register_operand" "=r")
3757         (zero_extend:DI
3758           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3759                        (match_operand:SI 2 "register_operand" "r"))))]
3760   ""
3761   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3762   [(set_attr "type" "logic_reg")]
3765 (define_insn "*xor_one_cmplsidi3_ze"
3766   [(set (match_operand:DI 0 "register_operand" "=r")
3767         (zero_extend:DI
3768           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3769                           (match_operand:SI 2 "register_operand" "r")))))]
3770   ""
3771   "eon\\t%w0, %w1, %w2"
3772   [(set_attr "type" "logic_reg")]
3775 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3776 ;; eon does not operate on SIMD registers so the vector variant must be split.
3777 (define_insn_and_split "*xor_one_cmpl<mode>3"
3778   [(set (match_operand:GPI 0 "register_operand" "=r,w")
3779         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3780                           (match_operand:GPI 2 "register_operand" "r,w"))))]
3781   ""
3782   "@
3783   eon\\t%<w>0, %<w>1, %<w>2
3784   #"
3785   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3786   [(set (match_operand:GPI 0 "register_operand" "=w")
3787         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3788                  (match_operand:GPI 2 "register_operand" "w")))
3789    (set (match_dup 0) (not:GPI (match_dup 0)))]
3790   ""
3791   [(set_attr "type" "logic_reg,multiple")
3792    (set_attr "simd" "*,yes")]
3795 (define_insn "*and_one_cmpl<mode>3_compare0"
3796   [(set (reg:CC_NZ CC_REGNUM)
3797         (compare:CC_NZ
3798          (and:GPI (not:GPI
3799                    (match_operand:GPI 1 "register_operand" "r"))
3800                   (match_operand:GPI 2 "register_operand" "r"))
3801          (const_int 0)))
3802    (set (match_operand:GPI 0 "register_operand" "=r")
3803         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3804   ""
3805   "bics\\t%<w>0, %<w>2, %<w>1"
3806   [(set_attr "type" "logics_reg")]
3809 ;; zero_extend version of above
3810 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3811   [(set (reg:CC_NZ CC_REGNUM)
3812         (compare:CC_NZ
3813          (and:SI (not:SI
3814                   (match_operand:SI 1 "register_operand" "r"))
3815                  (match_operand:SI 2 "register_operand" "r"))
3816          (const_int 0)))
3817    (set (match_operand:DI 0 "register_operand" "=r")
3818         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3819   ""
3820   "bics\\t%w0, %w2, %w1"
3821   [(set_attr "type" "logics_reg")]
3824 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3825   [(set (reg:CC_NZ CC_REGNUM)
3826     (compare:CC_NZ
3827      (and:GPI (not:GPI
3828            (match_operand:GPI 0 "register_operand" "r"))
3829           (match_operand:GPI 1 "register_operand" "r"))
3830      (const_int 0)))]
3831   ""
3832   "bics\\t<w>zr, %<w>1, %<w>0"
3833   [(set_attr "type" "logics_reg")]
3836 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3837   [(set (match_operand:GPI 0 "register_operand" "=r")
3838         (LOGICAL:GPI (not:GPI
3839                       (SHIFT:GPI
3840                        (match_operand:GPI 1 "register_operand" "r")
3841                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3842                      (match_operand:GPI 3 "register_operand" "r")))]
3843   ""
3844   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3845   [(set_attr "type" "logic_shift_imm")]
3848 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3849   [(set (match_operand:GPI 0 "register_operand" "=r")
3850         (not:GPI (xor:GPI
3851                       (SHIFT:GPI
3852                        (match_operand:GPI 1 "register_operand" "r")
3853                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3854                      (match_operand:GPI 3 "register_operand" "r"))))]
3855   ""
3856   "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3857   [(set_attr "type" "logic_shift_imm")]
3860 ;; Zero-extend version of the above.
3861 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3862   [(set (match_operand:DI 0 "register_operand" "=r")
3863         (zero_extend:DI
3864           (not:SI (xor:SI
3865                     (SHIFT:SI
3866                       (match_operand:SI 1 "register_operand" "r")
3867                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3868                     (match_operand:SI 3 "register_operand" "r")))))]
3869   ""
3870   "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3871   [(set_attr "type" "logic_shift_imm")]
3874 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3875   [(set (reg:CC_NZ CC_REGNUM)
3876         (compare:CC_NZ
3877          (and:GPI (not:GPI
3878                    (SHIFT:GPI
3879                     (match_operand:GPI 1 "register_operand" "r")
3880                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3881                   (match_operand:GPI 3 "register_operand" "r"))
3882          (const_int 0)))
3883    (set (match_operand:GPI 0 "register_operand" "=r")
3884         (and:GPI (not:GPI
3885                   (SHIFT:GPI
3886                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
3887   ""
3888   "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3889   [(set_attr "type" "logics_shift_imm")]
3892 ;; zero_extend version of above
3893 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3894   [(set (reg:CC_NZ CC_REGNUM)
3895         (compare:CC_NZ
3896          (and:SI (not:SI
3897                   (SHIFT:SI
3898                    (match_operand:SI 1 "register_operand" "r")
3899                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3900                  (match_operand:SI 3 "register_operand" "r"))
3901          (const_int 0)))
3902    (set (match_operand:DI 0 "register_operand" "=r")
3903         (zero_extend:DI (and:SI
3904                          (not:SI
3905                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3906   ""
3907   "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3908   [(set_attr "type" "logics_shift_imm")]
3911 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3912   [(set (reg:CC_NZ CC_REGNUM)
3913     (compare:CC_NZ
3914      (and:GPI (not:GPI
3915            (SHIFT:GPI
3916             (match_operand:GPI 0 "register_operand" "r")
3917             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3918           (match_operand:GPI 2 "register_operand" "r"))
3919      (const_int 0)))]
3920   ""
3921   "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3922   [(set_attr "type" "logics_shift_imm")]
3925 (define_insn "clz<mode>2"
3926   [(set (match_operand:GPI 0 "register_operand" "=r")
3927         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3928   ""
3929   "clz\\t%<w>0, %<w>1"
3930   [(set_attr "type" "clz")]
3933 (define_expand "ffs<mode>2"
3934   [(match_operand:GPI 0 "register_operand")
3935    (match_operand:GPI 1 "register_operand")]
3936   ""
3937   {
3938     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3939     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3941     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3942     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3943     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3944     DONE;
3945   }
3948 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
3950 ;; MOV  v.1d, x0
3951 ;; CNT  v1.8b, v.8b
3952 ;; ADDV b2, v1.8b
3953 ;; MOV  w0, v2.b[0]
3955 (define_expand "popcount<mode>2"
3956   [(match_operand:GPI 0 "register_operand")
3957    (match_operand:GPI 1 "register_operand")]
3958   "TARGET_SIMD"
3960   rtx v = gen_reg_rtx (V8QImode);
3961   rtx v1 = gen_reg_rtx (V8QImode);
3962   rtx r = gen_reg_rtx (QImode);
3963   rtx in = operands[1];
3964   rtx out = operands[0];
3965   if(<MODE>mode == SImode)
3966     {
3967       rtx tmp;
3968       tmp = gen_reg_rtx (DImode);
3969       /* If we have SImode, zero extend to DImode, pop count does
3970          not change if we have extra zeros. */
3971       emit_insn (gen_zero_extendsidi2 (tmp, in));
3972       in = tmp;
3973     }
3974   emit_move_insn (v, gen_lowpart (V8QImode, in));
3975   emit_insn (gen_popcountv8qi2 (v1, v));
3976   emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
3977   emit_insn (gen_zero_extendqi<mode>2 (out, r));
3978   DONE;
3981 (define_insn "clrsb<mode>2"
3982   [(set (match_operand:GPI 0 "register_operand" "=r")
3983         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3984   ""
3985   "cls\\t%<w>0, %<w>1"
3986   [(set_attr "type" "clz")]
3989 (define_insn "rbit<mode>2"
3990   [(set (match_operand:GPI 0 "register_operand" "=r")
3991         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3992   ""
3993   "rbit\\t%<w>0, %<w>1"
3994   [(set_attr "type" "rbit")]
3997 ;; Split after reload into RBIT + CLZ.  Since RBIT is represented as an UNSPEC
3998 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3999 ;; expression and split after reload to enable scheduling them apart if
4000 ;; needed.
4002 (define_insn_and_split "ctz<mode>2"
4003  [(set (match_operand:GPI           0 "register_operand" "=r")
4004        (ctz:GPI (match_operand:GPI  1 "register_operand" "r")))]
4005   ""
4006   "#"
4007   "reload_completed"
4008   [(const_int 0)]
4009   "
4010   emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
4011   emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
4012   DONE;
4015 (define_insn "*and<mode>_compare0"
4016   [(set (reg:CC_NZ CC_REGNUM)
4017         (compare:CC_NZ
4018          (match_operand:SHORT 0 "register_operand" "r")
4019          (const_int 0)))]
4020   ""
4021   "tst\\t%<w>0, <short_mask>"
4022   [(set_attr "type" "alus_imm")]
4025 (define_insn "*ands<mode>_compare0"
4026   [(set (reg:CC_NZ CC_REGNUM)
4027         (compare:CC_NZ
4028          (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
4029          (const_int 0)))
4030    (set (match_operand:GPI 0 "register_operand" "=r")
4031         (zero_extend:GPI (match_dup 1)))]
4032   ""
4033   "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
4034   [(set_attr "type" "alus_imm")]
4037 (define_insn "*and<mode>3nr_compare0"
4038   [(set (reg:CC_NZ CC_REGNUM)
4039         (compare:CC_NZ
4040          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
4041                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
4042          (const_int 0)))]
4043   ""
4044   "@
4045    tst\\t%<w>0, %<w>1
4046    tst\\t%<w>0, %1"
4047   [(set_attr "type" "logics_reg,logics_imm")]
4050 (define_split
4051   [(set (reg:CC_NZ CC_REGNUM)
4052         (compare:CC_NZ
4053          (and:GPI (match_operand:GPI 0 "register_operand")
4054                   (match_operand:GPI 1 "aarch64_mov_imm_operand"))
4055          (const_int 0)))
4056    (clobber (match_operand:SI 2 "register_operand"))]
4057   ""
4058   [(set (match_dup 2) (match_dup 1))
4059    (set (reg:CC_NZ CC_REGNUM)
4060         (compare:CC_NZ
4061          (and:GPI (match_dup 0)
4062                   (match_dup 2))
4063          (const_int 0)))]
4066 (define_insn "*and<mode>3nr_compare0_zextract"
4067   [(set (reg:CC_NZ CC_REGNUM)
4068         (compare:CC_NZ
4069          (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
4070                   (match_operand:GPI 1 "const_int_operand" "n")
4071                   (match_operand:GPI 2 "const_int_operand" "n"))
4072          (const_int 0)))]
4073   "INTVAL (operands[1]) > 0
4074    && ((INTVAL (operands[1]) + INTVAL (operands[2]))
4075         <= GET_MODE_BITSIZE (<MODE>mode))
4076    && aarch64_bitmask_imm (
4077         UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
4078                                                  operands[2])),
4079         <MODE>mode)"
4080   {
4081     operands[1]
4082       = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
4083     return "tst\\t%<w>0, %1";
4084   }
4085   [(set_attr "type" "logics_shift_imm")]
4088 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
4089   [(set (reg:CC_NZ CC_REGNUM)
4090         (compare:CC_NZ
4091          (and:GPI (SHIFT:GPI
4092                    (match_operand:GPI 0 "register_operand" "r")
4093                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
4094                   (match_operand:GPI 2 "register_operand" "r"))
4095         (const_int 0)))]
4096   ""
4097   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
4098   [(set_attr "type" "logics_shift_imm")]
4101 (define_split
4102   [(set (reg:CC_NZ CC_REGNUM)
4103         (compare:CC_NZ
4104          (and:GPI (SHIFT:GPI
4105                    (match_operand:GPI 0 "register_operand")
4106                    (match_operand:QI 1 "aarch64_shift_imm_<mode>"))
4107                   (match_operand:GPI 2 "aarch64_mov_imm_operand"))
4108         (const_int 0)))
4109     (clobber (match_operand:SI 3 "register_operand"))]
4110   ""
4111   [(set (match_dup 3) (match_dup 2))
4112    (set (reg:CC_NZ CC_REGNUM)
4113         (compare:CC_NZ
4114          (and:GPI (SHIFT:GPI
4115                    (match_dup 0)
4116                    (match_dup 1))
4117                   (match_dup 3))
4118          (const_int 0)))]
4121 ;; -------------------------------------------------------------------
4122 ;; Shifts
4123 ;; -------------------------------------------------------------------
4125 (define_expand "<optab><mode>3"
4126   [(set (match_operand:GPI 0 "register_operand")
4127         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
4128                     (match_operand:QI 2 "aarch64_reg_or_imm")))]
4129   ""
4130   {
4131     if (CONST_INT_P (operands[2]))
4132       {
4133         operands[2] = GEN_INT (INTVAL (operands[2])
4134                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4136         if (operands[2] == const0_rtx)
4137           {
4138             emit_insn (gen_mov<mode> (operands[0], operands[1]));
4139             DONE;
4140           }
4141       }
4142   }
4145 (define_expand "ashl<mode>3"
4146   [(set (match_operand:SHORT 0 "register_operand")
4147         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
4148                       (match_operand:QI 2 "const_int_operand")))]
4149   ""
4150   {
4151     operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
4153     if (operands[2] == const0_rtx)
4154       {
4155         emit_insn (gen_mov<mode> (operands[0], operands[1]));
4156         DONE;
4157       }
4158   }
4161 (define_expand "rotr<mode>3"
4162   [(set (match_operand:GPI 0 "register_operand")
4163         (rotatert:GPI (match_operand:GPI 1 "register_operand")
4164                       (match_operand:QI 2 "aarch64_reg_or_imm")))]
4165   ""
4166   {
4167     if (CONST_INT_P (operands[2]))
4168       {
4169         operands[2] = GEN_INT (INTVAL (operands[2])
4170                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4172         if (operands[2] == const0_rtx)
4173           {
4174             emit_insn (gen_mov<mode> (operands[0], operands[1]));
4175             DONE;
4176           }
4177       }
4178   }
4181 (define_expand "rotl<mode>3"
4182   [(set (match_operand:GPI 0 "register_operand")
4183         (rotatert:GPI (match_operand:GPI 1 "register_operand")
4184                       (match_operand:QI 2 "aarch64_reg_or_imm")))]
4185   ""
4186   {
4187     /* (SZ - cnt) % SZ == -cnt % SZ */
4188     if (CONST_INT_P (operands[2]))
4189       {
4190         operands[2] = GEN_INT ((-INTVAL (operands[2]))
4191                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4192         if (operands[2] == const0_rtx)
4193           {
4194             emit_insn (gen_mov<mode> (operands[0], operands[1]));
4195             DONE;
4196           }
4197       }
4198     else
4199       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
4200                                         NULL_RTX, 1);
4201   }
4204 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4205 ;; they truncate the shift/rotate amount by the size of the registers they
4206 ;; operate on: 32 for W-regs, 64 for X-regs.  This allows us to optimise away
4207 ;; such redundant masking instructions.  GCC can do that automatically when
4208 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4209 ;; because some of the SISD shift alternatives don't perform this truncations.
4210 ;; So this pattern exists to catch such cases.
4212 (define_insn "*aarch64_<optab>_reg_<mode>3_mask1"
4213   [(set (match_operand:GPI 0 "register_operand" "=r")
4214         (SHIFT:GPI
4215           (match_operand:GPI 1 "register_operand" "r")
4216           (match_operator 4 "subreg_lowpart_operator"
4217            [(and:GPI (match_operand:GPI 2 "register_operand" "r")
4218                      (match_operand 3 "const_int_operand" "n"))])))]
4219   "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
4220   "<shift>\t%<w>0, %<w>1, %<w>2"
4221   [(set_attr "type" "shift_reg")]
4224 (define_insn_and_split "*aarch64_<optab>_reg_<mode>3_neg_mask2"
4225   [(set (match_operand:GPI 0 "register_operand" "=&r")
4226         (SHIFT:GPI
4227           (match_operand:GPI 1 "register_operand" "r")
4228           (match_operator 4 "subreg_lowpart_operator"
4229           [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r")
4230                            (match_operand 3 "const_int_operand" "n")))])))]
4231   "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)"
4232   "#"
4233   "&& true"
4234   [(const_int 0)]
4235   {
4236     rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4237                : lowpart_subreg (SImode, operands[0], <MODE>mode));
4238     emit_insn (gen_negsi2 (tmp, operands[2]));
4240     rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]);
4241     rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op,
4242                                      SUBREG_BYTE (operands[4]));
4243     emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp));
4244     DONE;
4245   }
4248 (define_insn_and_split "*aarch64_ashl_reg_<mode>3_minus_mask"
4249   [(set (match_operand:GPI 0 "register_operand" "=&r")
4250         (ashift:GPI
4251           (match_operand:GPI 1 "register_operand" "r")
4252           (minus:QI (match_operand 2 "const_int_operand" "n")
4253                     (match_operator 5 "subreg_lowpart_operator"
4254                     [(and:SI (match_operand:SI 3 "register_operand" "r")
4255                              (match_operand 4 "const_int_operand" "n"))]))))]
4256   "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)
4257    && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
4258   "#"
4259   "&& true"
4260   [(const_int 0)]
4261   {
4262     rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4263                : operands[0]);
4265     emit_insn (gen_negsi2 (tmp, operands[3]));
4267     rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]);
4268     rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op,
4269                                      SUBREG_BYTE (operands[5]));
4271     emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp));
4272     DONE;
4273   }
4276 (define_insn "*aarch64_<optab>_reg_di3_mask2"
4277   [(set (match_operand:DI 0 "register_operand" "=r")
4278         (SHIFT:DI
4279           (match_operand:DI 1 "register_operand" "r")
4280           (match_operator 4 "subreg_lowpart_operator"
4281            [(and:SI (match_operand:SI 2 "register_operand" "r")
4282                     (match_operand 3 "const_int_operand" "n"))])))]
4283   "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)"
4285   rtx xop[3];
4286   xop[0] = operands[0];
4287   xop[1] = operands[1];
4288   xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]);
4289   output_asm_insn ("<shift>\t%x0, %x1, %x2", xop);
4290   return "";
4292   [(set_attr "type" "shift_reg")]
4295 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>3"
4296   [(set (match_operand:GPI 0 "register_operand" "=&r")
4297         (ASHIFT:GPI
4298           (match_operand:GPI 1 "register_operand" "r")
4299           (minus:QI (match_operand 2 "const_int_operand" "n")
4300                     (match_operand:QI 3 "register_operand" "r"))))]
4301   "INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
4302   "#"
4303   "&& true"
4304   [(const_int 0)]
4305   {
4306     rtx subreg_tmp = gen_lowpart (SImode, operands[3]);
4308     rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4309                : gen_lowpart (SImode, operands[0]));
4311     emit_insn (gen_negsi2 (tmp, subreg_tmp));
4313     rtx and_op = gen_rtx_AND (SImode, tmp,
4314                               GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1));
4316     rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
4318     emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp2));
4319     DONE;
4320   }
4321   [(set_attr "length" "8")]
4324 ;; Logical left shift using SISD or Integer instruction
4325 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
4326   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
4327         (ashift:GPI
4328           (match_operand:GPI 1 "register_operand" "r,r,w,w")
4329           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
4330   ""
4331   "@
4332    lsl\t%<w>0, %<w>1, %2
4333    lsl\t%<w>0, %<w>1, %<w>2
4334    shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4335    ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
4336   [(set_attr "simd" "no,no,yes,yes")
4337    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
4340 ;; Logical right shift using SISD or Integer instruction
4341 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
4342   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4343         (lshiftrt:GPI
4344          (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4345          (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>"
4346                               "Us<cmode>,r,Us<cmode_simd>,w,0")))]
4347   ""
4348   "@
4349    lsr\t%<w>0, %<w>1, %2
4350    lsr\t%<w>0, %<w>1, %<w>2
4351    ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4352    #
4353    #"
4354   [(set_attr "simd" "no,no,yes,yes,yes")
4355    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4358 (define_split
4359   [(set (match_operand:DI 0 "aarch64_simd_register")
4360         (lshiftrt:DI
4361            (match_operand:DI 1 "aarch64_simd_register")
4362            (match_operand:QI 2 "aarch64_simd_register")))]
4363   "TARGET_SIMD && reload_completed"
4364   [(set (match_dup 3)
4365         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4366    (set (match_dup 0)
4367         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4368   {
4369     operands[3] = gen_lowpart (QImode, operands[0]);
4370   }
4373 (define_split
4374   [(set (match_operand:SI 0 "aarch64_simd_register")
4375         (lshiftrt:SI
4376            (match_operand:SI 1 "aarch64_simd_register")
4377            (match_operand:QI 2 "aarch64_simd_register")))]
4378   "TARGET_SIMD && reload_completed"
4379   [(set (match_dup 3)
4380         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4381    (set (match_dup 0)
4382         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4383   {
4384     operands[3] = gen_lowpart (QImode, operands[0]);
4385   }
4388 ;; Arithmetic right shift using SISD or Integer instruction
4389 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4390   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4391         (ashiftrt:GPI
4392           (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4393           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di"
4394                                "Us<cmode>,r,Us<cmode_simd>,w,0")))]
4395   ""
4396   "@
4397    asr\t%<w>0, %<w>1, %2
4398    asr\t%<w>0, %<w>1, %<w>2
4399    sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4400    #
4401    #"
4402   [(set_attr "simd" "no,no,yes,yes,yes")
4403    (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4406 (define_split
4407   [(set (match_operand:DI 0 "aarch64_simd_register")
4408         (ashiftrt:DI
4409            (match_operand:DI 1 "aarch64_simd_register")
4410            (match_operand:QI 2 "aarch64_simd_register")))]
4411   "TARGET_SIMD && reload_completed"
4412   [(set (match_dup 3)
4413         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4414    (set (match_dup 0)
4415         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4417   operands[3] = gen_lowpart (QImode, operands[0]);
4421 (define_split
4422   [(set (match_operand:SI 0 "aarch64_simd_register")
4423         (ashiftrt:SI
4424            (match_operand:SI 1 "aarch64_simd_register")
4425            (match_operand:QI 2 "aarch64_simd_register")))]
4426   "TARGET_SIMD && reload_completed"
4427   [(set (match_dup 3)
4428         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4429    (set (match_dup 0)
4430         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4432   operands[3] = gen_lowpart (QImode, operands[0]);
4436 (define_insn "*aarch64_sisd_ushl"
4437   [(set (match_operand:DI 0 "register_operand" "=w")
4438         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4439                     (match_operand:QI 2 "register_operand" "w")]
4440                    UNSPEC_SISD_USHL))]
4441   "TARGET_SIMD"
4442   "ushl\t%d0, %d1, %d2"
4443   [(set_attr "simd" "yes")
4444    (set_attr "type" "neon_shift_reg")]
4447 (define_insn "*aarch64_ushl_2s"
4448   [(set (match_operand:SI 0 "register_operand" "=w")
4449         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4450                     (match_operand:QI 2 "register_operand" "w")]
4451                    UNSPEC_USHL_2S))]
4452   "TARGET_SIMD"
4453   "ushl\t%0.2s, %1.2s, %2.2s"
4454   [(set_attr "simd" "yes")
4455    (set_attr "type" "neon_shift_reg")]
4458 (define_insn "*aarch64_sisd_sshl"
4459   [(set (match_operand:DI 0 "register_operand" "=w")
4460         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4461                     (match_operand:QI 2 "register_operand" "w")]
4462                    UNSPEC_SISD_SSHL))]
4463   "TARGET_SIMD"
4464   "sshl\t%d0, %d1, %d2"
4465   [(set_attr "simd" "yes")
4466    (set_attr "type" "neon_shift_reg")]
4469 (define_insn "*aarch64_sshl_2s"
4470   [(set (match_operand:SI 0 "register_operand" "=w")
4471         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4472                     (match_operand:QI 2 "register_operand" "w")]
4473                    UNSPEC_SSHL_2S))]
4474   "TARGET_SIMD"
4475   "sshl\t%0.2s, %1.2s, %2.2s"
4476   [(set_attr "simd" "yes")
4477    (set_attr "type" "neon_shift_reg")]
4480 (define_insn "*aarch64_sisd_neg_qi"
4481   [(set (match_operand:QI 0 "register_operand" "=w")
4482         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4483                    UNSPEC_SISD_NEG))]
4484   "TARGET_SIMD"
4485   "neg\t%d0, %d1"
4486   [(set_attr "simd" "yes")
4487    (set_attr "type" "neon_neg")]
4490 ;; Rotate right
4491 (define_insn "*ror<mode>3_insn"
4492   [(set (match_operand:GPI 0 "register_operand" "=r,r")
4493      (rotatert:GPI
4494        (match_operand:GPI 1 "register_operand" "r,r")
4495        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4496   ""
4497   "@
4498    ror\\t%<w>0, %<w>1, %2
4499    ror\\t%<w>0, %<w>1, %<w>2"
4500   [(set_attr "type" "rotate_imm,shift_reg")]
4503 ;; zero_extend version of above
4504 (define_insn "*<optab>si3_insn_uxtw"
4505   [(set (match_operand:DI 0 "register_operand" "=r,r")
4506         (zero_extend:DI (SHIFT:SI
4507          (match_operand:SI 1 "register_operand" "r,r")
4508          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4509   ""
4510   "@
4511    <shift>\\t%w0, %w1, %2
4512    <shift>\\t%w0, %w1, %w2"
4513   [(set_attr "type" "bfx,shift_reg")]
4516 (define_insn "*<optab><mode>3_insn"
4517   [(set (match_operand:SHORT 0 "register_operand" "=r")
4518         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4519                       (match_operand 2 "const_int_operand" "n")))]
4520   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4522   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4523   return "<bfshift>\t%w0, %w1, %2, %3";
4525   [(set_attr "type" "bfx")]
4528 (define_insn "*extr<mode>5_insn"
4529   [(set (match_operand:GPI 0 "register_operand" "=r")
4530         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4531                              (match_operand 3 "const_int_operand" "n"))
4532                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4533                                (match_operand 4 "const_int_operand" "n"))))]
4534   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4535    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4536   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4537   [(set_attr "type" "rotate_imm")]
4540 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4541 ;; so we have to match both orderings.
4542 (define_insn "*extr<mode>5_insn_alt"
4543   [(set (match_operand:GPI 0 "register_operand" "=r")
4544         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4545                                 (match_operand 4 "const_int_operand" "n"))
4546                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4547                               (match_operand 3 "const_int_operand" "n"))))]
4548   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4549    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4550        == GET_MODE_BITSIZE (<MODE>mode))"
4551   "extr\\t%<w>0, %<w>1, %<w>2, %4"
4552   [(set_attr "type" "rotate_imm")]
4555 ;; zero_extend version of the above
4556 (define_insn "*extrsi5_insn_uxtw"
4557   [(set (match_operand:DI 0 "register_operand" "=r")
4558         (zero_extend:DI
4559          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4560                             (match_operand 3 "const_int_operand" "n"))
4561                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4562                               (match_operand 4 "const_int_operand" "n")))))]
4563   "UINTVAL (operands[3]) < 32 &&
4564    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4565   "extr\\t%w0, %w1, %w2, %4"
4566   [(set_attr "type" "rotate_imm")]
4569 (define_insn "*extrsi5_insn_uxtw_alt"
4570   [(set (match_operand:DI 0 "register_operand" "=r")
4571         (zero_extend:DI
4572          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4573                                (match_operand 4 "const_int_operand" "n"))
4574                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
4575                             (match_operand 3 "const_int_operand" "n")))))]
4576   "UINTVAL (operands[3]) < 32 &&
4577    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4578   "extr\\t%w0, %w1, %w2, %4"
4579   [(set_attr "type" "rotate_imm")]
4582 (define_insn "*ror<mode>3_insn"
4583   [(set (match_operand:GPI 0 "register_operand" "=r")
4584         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4585                     (match_operand 2 "const_int_operand" "n")))]
4586   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4588   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4589   return "ror\\t%<w>0, %<w>1, %3";
4591   [(set_attr "type" "rotate_imm")]
4594 ;; zero_extend version of the above
4595 (define_insn "*rorsi3_insn_uxtw"
4596   [(set (match_operand:DI 0 "register_operand" "=r")
4597         (zero_extend:DI
4598          (rotate:SI (match_operand:SI 1 "register_operand" "r")
4599                     (match_operand 2 "const_int_operand" "n"))))]
4600   "UINTVAL (operands[2]) < 32"
4602   operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4603   return "ror\\t%w0, %w1, %3";
4605   [(set_attr "type" "rotate_imm")]
4608 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4609   [(set (match_operand:GPI 0 "register_operand" "=r")
4610         (ANY_EXTEND:GPI
4611          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4612                        (match_operand 2 "const_int_operand" "n"))))]
4613   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4615   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4616   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4618   [(set_attr "type" "bfx")]
4621 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4622   [(set (match_operand:GPI 0 "register_operand" "=r")
4623         (zero_extend:GPI
4624          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4625                          (match_operand 2 "const_int_operand" "n"))))]
4626   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4628   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4629   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4631   [(set_attr "type" "bfx")]
4634 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4635   [(set (match_operand:GPI 0 "register_operand" "=r")
4636         (sign_extend:GPI
4637          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4638                          (match_operand 2 "const_int_operand" "n"))))]
4639   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4641   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4642   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4644   [(set_attr "type" "bfx")]
4647 ;; -------------------------------------------------------------------
4648 ;; Bitfields
4649 ;; -------------------------------------------------------------------
4651 (define_expand "<optab>"
4652   [(set (match_operand:DI 0 "register_operand" "=r")
4653         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4654                         (match_operand 2
4655                           "aarch64_simd_shift_imm_offset_di")
4656                         (match_operand 3 "aarch64_simd_shift_imm_di")))]
4657   ""
4658   {
4659     if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4660                    1, GET_MODE_BITSIZE (DImode) - 1))
4661      FAIL;
4662   }
4666 (define_insn "*<optab><mode>"
4667   [(set (match_operand:GPI 0 "register_operand" "=r")
4668         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4669                          (match_operand 2
4670                            "aarch64_simd_shift_imm_offset_<mode>" "n")
4671                          (match_operand 3
4672                            "aarch64_simd_shift_imm_<mode>" "n")))]
4673   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4674              1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4675   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4676   [(set_attr "type" "bfx")]
4679 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4680 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4681 (define_split
4682   [(set (match_operand:DI 0 "register_operand")
4683         (zero_extract:DI (match_operand:DI 1 "register_operand")
4684                          (match_operand 2
4685                            "aarch64_simd_shift_imm_offset_di")
4686                          (match_operand 3
4687                            "aarch64_simd_shift_imm_di")))]
4688   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4689              GET_MODE_BITSIZE (DImode) - 1)
4690    && (INTVAL (operands[2]) + INTVAL (operands[3]))
4691        == GET_MODE_BITSIZE (SImode)"
4692   [(set (match_dup 0)
4693         (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4694   {
4695     operands[4] = gen_lowpart (SImode, operands[1]);
4696   }
4699 ;; Bitfield Insert (insv)
4700 (define_expand "insv<mode>"
4701   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4702                           (match_operand 1 "const_int_operand")
4703                           (match_operand 2 "const_int_operand"))
4704         (match_operand:GPI 3 "general_operand"))]
4705   ""
4707   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4708   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4709   rtx value = operands[3];
4711   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4712     FAIL;
4714   if (CONST_INT_P (value))
4715     {
4716       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4718       /* Prefer AND/OR for inserting all zeros or all ones.  */
4719       if ((UINTVAL (value) & mask) == 0
4720            || (UINTVAL (value) & mask) == mask)
4721         FAIL;
4723       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
4724       if (width == 16 && (pos % 16) == 0)
4725         DONE;
4726     }
4727   operands[3] = force_reg (<MODE>mode, value);
4730 (define_insn "*insv_reg<mode>"
4731   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4732                           (match_operand 1 "const_int_operand" "n")
4733                           (match_operand 2 "const_int_operand" "n"))
4734         (match_operand:GPI 3 "register_operand" "r"))]
4735   "!(UINTVAL (operands[1]) == 0
4736      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4737          > GET_MODE_BITSIZE (<MODE>mode)))"
4738   "bfi\\t%<w>0, %<w>3, %2, %1"
4739   [(set_attr "type" "bfm")]
4742 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4743   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4744                           (match_operand 1 "const_int_operand" "n")
4745                           (match_operand 2 "const_int_operand" "n"))
4746         (zero_extend:GPI (match_operand:ALLX 3  "register_operand" "r")))]
4747   "UINTVAL (operands[1]) <= <ALLX:sizen>"
4748   "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4749   [(set_attr "type" "bfm")]
4752 (define_insn "*extr_insv_lower_reg<mode>"
4753   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4754                           (match_operand 1 "const_int_operand" "n")
4755                           (const_int 0))
4756         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4757                           (match_dup 1)
4758                           (match_operand 3 "const_int_operand" "n")))]
4759   "!(UINTVAL (operands[1]) == 0
4760      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4761          > GET_MODE_BITSIZE (<MODE>mode)))"
4762   "bfxil\\t%<w>0, %<w>2, %3, %1"
4763   [(set_attr "type" "bfm")]
4766 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4767   [(set (match_operand:GPI 0 "register_operand" "=r")
4768         (ashift:GPI (ANY_EXTEND:GPI
4769                      (match_operand:ALLX 1 "register_operand" "r"))
4770                     (match_operand 2 "const_int_operand" "n")))]
4771   "UINTVAL (operands[2]) < <GPI:sizen>"
4773   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4774               ? GEN_INT (<ALLX:sizen>)
4775               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4776   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4778   [(set_attr "type" "bfx")]
4781 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4783 (define_insn "*andim_ashift<mode>_bfiz"
4784   [(set (match_operand:GPI 0 "register_operand" "=r")
4785         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4786                              (match_operand 2 "const_int_operand" "n"))
4787                  (match_operand 3 "const_int_operand" "n")))]
4788   "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4789   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4790   [(set_attr "type" "bfx")]
4793 ;; When the bit position and width of the equivalent extraction add up to 32
4794 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4795 ;; zero-extension of the X-reg.
4796 (define_split
4797   [(set (match_operand:DI 0 "register_operand")
4798         (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4799                              (match_operand 2 "const_int_operand"))
4800                  (match_operand 3 "const_int_operand")))]
4801  "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4802   && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4803       == GET_MODE_BITSIZE (SImode)"
4804   [(set (match_dup 0)
4805         (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4806   {
4807     operands[4] = gen_lowpart (SImode, operands[1]);
4808   }
4811 (define_insn "bswap<mode>2"
4812   [(set (match_operand:GPI 0 "register_operand" "=r")
4813         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4814   ""
4815   "rev\\t%<w>0, %<w>1"
4816   [(set_attr "type" "rev")]
4819 (define_insn "bswaphi2"
4820   [(set (match_operand:HI 0 "register_operand" "=r")
4821         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4822   ""
4823   "rev16\\t%w0, %w1"
4824   [(set_attr "type" "rev")]
4827 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4828 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4829 ;; each valid permutation.
4831 (define_insn "rev16<mode>2"
4832   [(set (match_operand:GPI 0 "register_operand" "=r")
4833         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4834                                       (const_int 8))
4835                           (match_operand:GPI 3 "const_int_operand" "n"))
4836                  (and:GPI (lshiftrt:GPI (match_dup 1)
4837                                         (const_int 8))
4838                           (match_operand:GPI 2 "const_int_operand" "n"))))]
4839   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4840    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4841   "rev16\\t%<w>0, %<w>1"
4842   [(set_attr "type" "rev")]
4845 (define_insn "rev16<mode>2_alt"
4846   [(set (match_operand:GPI 0 "register_operand" "=r")
4847         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4848                                         (const_int 8))
4849                           (match_operand:GPI 2 "const_int_operand" "n"))
4850                  (and:GPI (ashift:GPI (match_dup 1)
4851                                       (const_int 8))
4852                           (match_operand:GPI 3 "const_int_operand" "n"))))]
4853   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4854    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4855   "rev16\\t%<w>0, %<w>1"
4856   [(set_attr "type" "rev")]
4859 ;; zero_extend version of above
4860 (define_insn "*bswapsi2_uxtw"
4861   [(set (match_operand:DI 0 "register_operand" "=r")
4862         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4863   ""
4864   "rev\\t%w0, %w1"
4865   [(set_attr "type" "rev")]
4868 ;; -------------------------------------------------------------------
4869 ;; Floating-point intrinsics
4870 ;; -------------------------------------------------------------------
4872 ;; frint floating-point round to integral standard patterns.
4873 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4875 (define_insn "<frint_pattern><mode>2"
4876   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4877         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4878          FRINT))]
4879   "TARGET_FLOAT"
4880   "frint<frint_suffix>\\t%<s>0, %<s>1"
4881   [(set_attr "type" "f_rint<stype>")]
4884 ;; frcvt floating-point round to integer and convert standard patterns.
4885 ;; Expands to lbtrunc, lceil, lfloor, lround.
4886 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4887   [(set (match_operand:GPI 0 "register_operand" "=r")
4888         (FIXUORS:GPI
4889           (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4890            FCVT)))]
4891   "TARGET_FLOAT"
4892   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4893   [(set_attr "type" "f_cvtf2i")]
4896 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4897   [(set (match_operand:GPI 0 "register_operand" "=r")
4898         (FIXUORS:GPI
4899           (mult:GPF
4900             (match_operand:GPF 1 "register_operand" "w")
4901             (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4902   "TARGET_FLOAT
4903    && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4904                 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4905   {
4906     int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4907     char buf[64];
4908     snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4909     output_asm_insn (buf, operands);
4910     return "";
4911   }
4912   [(set_attr "type" "f_cvtf2i")]
4915 ;; fma - expand fma into patterns with the accumulator operand first since
4916 ;; reusing the accumulator results in better register allocation.
4917 ;; The register allocator considers copy preferences in operand order,
4918 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
4920 (define_expand "fma<mode>4"
4921   [(set (match_operand:GPF_F16 0 "register_operand")
4922         (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand")
4923                      (match_operand:GPF_F16 2 "register_operand")
4924                      (match_operand:GPF_F16 3 "register_operand")))]
4925   "TARGET_FLOAT"
4928 (define_insn "*aarch64_fma<mode>4"
4929   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4930         (fma:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w")
4931                      (match_operand:GPF_F16 3 "register_operand" "w")
4932                      (match_operand:GPF_F16 1 "register_operand" "w")))]
4933   "TARGET_FLOAT"
4934   "fmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
4935   [(set_attr "type" "fmac<stype>")]
4938 (define_expand "fnma<mode>4"
4939   [(set (match_operand:GPF_F16 0 "register_operand")
4940         (fma:GPF_F16
4941           (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand"))
4942           (match_operand:GPF_F16 2 "register_operand")
4943           (match_operand:GPF_F16 3 "register_operand")))]
4944   "TARGET_FLOAT"
4947 (define_insn "*aarch64_fnma<mode>4"
4948   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4949         (fma:GPF_F16
4950           (neg:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w"))
4951           (match_operand:GPF_F16 3 "register_operand" "w")
4952           (match_operand:GPF_F16 1 "register_operand" "w")))]
4953   "TARGET_FLOAT"
4954   "fmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
4955   [(set_attr "type" "fmac<stype>")]
4959 (define_expand "fms<mode>4"
4960   [(set (match_operand:GPF 0 "register_operand")
4961         (fma:GPF (match_operand:GPF 1 "register_operand")
4962                  (match_operand:GPF 2 "register_operand")
4963                  (neg:GPF (match_operand:GPF 3 "register_operand"))))]
4964   "TARGET_FLOAT"
4967 (define_insn "*aarch64_fms<mode>4"
4968   [(set (match_operand:GPF 0 "register_operand" "=w")
4969         (fma:GPF (match_operand:GPF 2 "register_operand" "w")
4970                  (match_operand:GPF 3 "register_operand" "w")
4971                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
4972   "TARGET_FLOAT"
4973   "fnmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
4974   [(set_attr "type" "fmac<s>")]
4977 (define_expand "fnms<mode>4"
4978   [(set (match_operand:GPF 0 "register_operand")
4979         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand"))
4980                  (match_operand:GPF 2 "register_operand")
4981                  (neg:GPF (match_operand:GPF 3 "register_operand"))))]
4982   "TARGET_FLOAT"
4985 (define_insn "*aarch64_fnms<mode>4"
4986   [(set (match_operand:GPF 0 "register_operand" "=w")
4987         (fma:GPF (neg:GPF (match_operand:GPF 2 "register_operand" "w"))
4988                  (match_operand:GPF 3 "register_operand" "w")
4989                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
4990   "TARGET_FLOAT"
4991   "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
4992   [(set_attr "type" "fmac<s>")]
4995 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4996 (define_insn "*aarch64_fnmadd<mode>4"
4997   [(set (match_operand:GPF 0 "register_operand" "=w")
4998         (neg:GPF (fma:GPF (match_operand:GPF 2 "register_operand" "w")
4999                           (match_operand:GPF 3 "register_operand" "w")
5000                           (match_operand:GPF 1 "register_operand" "w"))))]
5001   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5002   "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5003   [(set_attr "type" "fmac<s>")]
5006 ;; -------------------------------------------------------------------
5007 ;; Floating-point conversions
5008 ;; -------------------------------------------------------------------
5010 (define_insn "extendsfdf2"
5011   [(set (match_operand:DF 0 "register_operand" "=w")
5012         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
5013   "TARGET_FLOAT"
5014   "fcvt\\t%d0, %s1"
5015   [(set_attr "type" "f_cvt")]
5018 (define_insn "extendhfsf2"
5019   [(set (match_operand:SF 0 "register_operand" "=w")
5020         (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
5021   "TARGET_FLOAT"
5022   "fcvt\\t%s0, %h1"
5023   [(set_attr "type" "f_cvt")]
5026 (define_insn "extendhfdf2"
5027   [(set (match_operand:DF 0 "register_operand" "=w")
5028         (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
5029   "TARGET_FLOAT"
5030   "fcvt\\t%d0, %h1"
5031   [(set_attr "type" "f_cvt")]
5034 (define_insn "truncdfsf2"
5035   [(set (match_operand:SF 0 "register_operand" "=w")
5036         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
5037   "TARGET_FLOAT"
5038   "fcvt\\t%s0, %d1"
5039   [(set_attr "type" "f_cvt")]
5042 (define_insn "truncsfhf2"
5043   [(set (match_operand:HF 0 "register_operand" "=w")
5044         (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
5045   "TARGET_FLOAT"
5046   "fcvt\\t%h0, %s1"
5047   [(set_attr "type" "f_cvt")]
5050 (define_insn "truncdfhf2"
5051   [(set (match_operand:HF 0 "register_operand" "=w")
5052         (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
5053   "TARGET_FLOAT"
5054   "fcvt\\t%h0, %d1"
5055   [(set_attr "type" "f_cvt")]
5058 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
5059 ;; and making r = w more expensive
5061 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>2"
5062   [(set (match_operand:GPI 0 "register_operand" "=w,?r")
5063         (FIXUORS:GPI (match_operand:<FCVT_TARGET> 1 "register_operand" "w,w")))]
5064   "TARGET_FLOAT"
5065   "@
5066    fcvtz<su>\t%<s>0, %<s>1
5067    fcvtz<su>\t%<w>0, %<s>1"
5068   [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
5071 ;; Convert HF -> SI or DI
5073 (define_insn "<optab>_trunchf<GPI:mode>2"
5074   [(set (match_operand:GPI 0 "register_operand" "=r")
5075         (FIXUORS:GPI (match_operand:HF 1 "register_operand" "w")))]
5076   "TARGET_FP_F16INST"
5077   "fcvtz<su>\t%<w>0, %h1"
5078   [(set_attr "type" "f_cvtf2i")]
5081 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
5082 ;; input in a fp register and output in a integer register
5084 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>2"
5085   [(set (match_operand:GPI 0 "register_operand" "=r")
5086         (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE> 1 "register_operand" "w")))]
5087   "TARGET_FLOAT"
5088   "fcvtz<su>\t%<w>0, %<fpw>1"
5089   [(set_attr "type" "f_cvtf2i")]
5092 (define_insn "<optab><fcvt_target><GPF:mode>2"
5093   [(set (match_operand:GPF 0 "register_operand" "=w,w")
5094         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,?r")))]
5095   "TARGET_FLOAT"
5096   "@
5097    <su_optab>cvtf\t%<GPF:s>0, %<s>1
5098    <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
5099   [(set_attr "simd" "yes,no")
5100    (set_attr "fp" "no,yes")
5101    (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
5104 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
5105   [(set (match_operand:GPF 0 "register_operand" "=w")
5106         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
5107   "TARGET_FLOAT"
5108   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
5109   [(set_attr "type" "f_cvti2f")]
5112 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
5113 ;; midend will arrange for an SImode conversion to HFmode to first go
5114 ;; through DFmode, then to HFmode.  But first it will try converting
5115 ;; to DImode then down, which would match our DImode pattern below and
5116 ;; give very poor code-generation.  So, we must provide our own emulation
5117 ;; of the mid-end logic.
5119 (define_insn "aarch64_fp16_<optab><mode>hf2"
5120   [(set (match_operand:HF 0 "register_operand" "=w")
5121         (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
5122   "TARGET_FP_F16INST"
5123   "<su_optab>cvtf\t%h0, %<w>1"
5124   [(set_attr "type" "f_cvti2f")]
5127 (define_expand "<optab>sihf2"
5128   [(set (match_operand:HF 0 "register_operand")
5129         (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
5130   "TARGET_FLOAT"
5132   if (TARGET_FP_F16INST)
5133     emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
5134   else
5135     {
5136       rtx convert_target = gen_reg_rtx (DFmode);
5137       emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
5138       emit_insn (gen_truncdfhf2 (operands[0], convert_target));
5139     }
5140   DONE;
5144 ;; For DImode there is no wide enough floating-point mode that we
5145 ;; can convert through natively (TFmode would work, but requires a library
5146 ;; call).  However, we know that any value >= 65504 will be rounded
5147 ;; to infinity on conversion.  This is well within the range of SImode, so
5148 ;; we can:
5149 ;;   Saturate to SImode.
5150 ;;   Convert from that to DFmode
5151 ;;   Convert from that to HFmode (phew!).
5152 ;; Note that the saturation to SImode requires the SIMD extensions.  If
5153 ;; we ever need to provide this pattern where the SIMD extensions are not
5154 ;; available, we would need a different approach.
5156 (define_expand "<optab>dihf2"
5157   [(set (match_operand:HF 0 "register_operand")
5158         (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
5159   "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
5161   if (TARGET_FP_F16INST)
5162     emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
5163   else
5164     {
5165       rtx sat_target = gen_reg_rtx (SImode);
5166       emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
5167       emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
5168     }
5170   DONE;
5174 ;; Convert between fixed-point and floating-point (scalar modes)
5176 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
5177   [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
5178         (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
5179                                    (match_operand:SI 2 "immediate_operand" "i, i")]
5180          FCVT_F2FIXED))]
5181   ""
5182   "@
5183    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
5184    <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
5185   [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
5186    (set_attr "fp" "yes, *")
5187    (set_attr "simd" "*, yes")]
5190 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
5191   [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
5192         (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
5193                                    (match_operand:SI 2 "immediate_operand" "i, i")]
5194          FCVT_FIXED2F))]
5195   ""
5196   "@
5197    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
5198    <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
5199   [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
5200    (set_attr "fp" "yes, *")
5201    (set_attr "simd" "*, yes")]
5204 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
5205   [(set (match_operand:GPI 0 "register_operand" "=r")
5206         (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
5207                      (match_operand:SI 2 "immediate_operand" "i")]
5208          FCVT_F2FIXED))]
5209   "TARGET_FP_F16INST"
5210    "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
5211   [(set_attr "type" "f_cvtf2i")]
5214 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
5215   [(set (match_operand:HF 0 "register_operand" "=w")
5216         (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
5217                     (match_operand:SI 2 "immediate_operand" "i")]
5218          FCVT_FIXED2F))]
5219   "TARGET_FP_F16INST"
5220   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
5221   [(set_attr "type" "f_cvti2f")]
5224 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
5225   [(set (match_operand:HI 0 "register_operand" "=w")
5226         (unspec:HI [(match_operand:HF 1 "register_operand" "w")
5227                     (match_operand:SI 2 "immediate_operand" "i")]
5228          FCVT_F2FIXED))]
5229   "TARGET_SIMD"
5230   "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
5231   [(set_attr "type" "neon_fp_to_int_s")]
5234 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
5235   [(set (match_operand:HF 0 "register_operand" "=w")
5236         (unspec:HF [(match_operand:HI 1 "register_operand" "w")
5237                     (match_operand:SI 2 "immediate_operand" "i")]
5238          FCVT_FIXED2F))]
5239   "TARGET_SIMD"
5240   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
5241   [(set_attr "type" "neon_int_to_fp_s")]
5244 ;; -------------------------------------------------------------------
5245 ;; Floating-point arithmetic
5246 ;; -------------------------------------------------------------------
5248 (define_insn "add<mode>3"
5249   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5250         (plus:GPF_F16
5251          (match_operand:GPF_F16 1 "register_operand" "w")
5252          (match_operand:GPF_F16 2 "register_operand" "w")))]
5253   "TARGET_FLOAT"
5254   "fadd\\t%<s>0, %<s>1, %<s>2"
5255   [(set_attr "type" "fadd<stype>")]
5258 (define_insn "sub<mode>3"
5259   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5260         (minus:GPF_F16
5261          (match_operand:GPF_F16 1 "register_operand" "w")
5262          (match_operand:GPF_F16 2 "register_operand" "w")))]
5263   "TARGET_FLOAT"
5264   "fsub\\t%<s>0, %<s>1, %<s>2"
5265   [(set_attr "type" "fadd<stype>")]
5268 (define_insn "mul<mode>3"
5269   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5270         (mult:GPF_F16
5271          (match_operand:GPF_F16 1 "register_operand" "w")
5272          (match_operand:GPF_F16 2 "register_operand" "w")))]
5273   "TARGET_FLOAT"
5274   "fmul\\t%<s>0, %<s>1, %<s>2"
5275   [(set_attr "type" "fmul<stype>")]
5278 (define_insn "*fnmul<mode>3"
5279   [(set (match_operand:GPF 0 "register_operand" "=w")
5280         (mult:GPF
5281                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
5282                  (match_operand:GPF 2 "register_operand" "w")))]
5283   "TARGET_FLOAT && !flag_rounding_math"
5284   "fnmul\\t%<s>0, %<s>1, %<s>2"
5285   [(set_attr "type" "fmul<s>")]
5288 (define_insn "*fnmul<mode>3"
5289   [(set (match_operand:GPF 0 "register_operand" "=w")
5290         (neg:GPF (mult:GPF
5291                  (match_operand:GPF 1 "register_operand" "w")
5292                  (match_operand:GPF 2 "register_operand" "w"))))]
5293   "TARGET_FLOAT"
5294   "fnmul\\t%<s>0, %<s>1, %<s>2"
5295   [(set_attr "type" "fmul<s>")]
5298 (define_expand "div<mode>3"
5299  [(set (match_operand:GPF_F16 0 "register_operand")
5300        (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
5301                     (match_operand:GPF_F16 2 "register_operand")))]
5302  "TARGET_FLOAT"
5304   if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
5305     DONE;
5307   operands[1] = force_reg (<MODE>mode, operands[1]);
5310 (define_insn "*div<mode>3"
5311   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5312         (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
5313                      (match_operand:GPF_F16 2 "register_operand" "w")))]
5314   "TARGET_FLOAT"
5315   "fdiv\\t%<s>0, %<s>1, %<s>2"
5316   [(set_attr "type" "fdiv<stype>")]
5319 (define_insn "neg<mode>2"
5320   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5321         (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5322   "TARGET_FLOAT"
5323   "fneg\\t%<s>0, %<s>1"
5324   [(set_attr "type" "ffarith<stype>")]
5327 (define_expand "sqrt<mode>2"
5328   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5329         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5330   "TARGET_FLOAT"
5332   if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
5333     DONE;
5336 (define_insn "*sqrt<mode>2"
5337   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5338         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5339   "TARGET_FLOAT"
5340   "fsqrt\\t%<s>0, %<s>1"
5341   [(set_attr "type" "fsqrt<stype>")]
5344 (define_insn "abs<mode>2"
5345   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5346         (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5347   "TARGET_FLOAT"
5348   "fabs\\t%<s>0, %<s>1"
5349   [(set_attr "type" "ffarith<stype>")]
5352 ;; Given that smax/smin do not specify the result when either input is NaN,
5353 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
5354 ;; for smin.
5356 (define_insn "smax<mode>3"
5357   [(set (match_operand:GPF 0 "register_operand" "=w")
5358         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
5359                   (match_operand:GPF 2 "register_operand" "w")))]
5360   "TARGET_FLOAT"
5361   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
5362   [(set_attr "type" "f_minmax<s>")]
5365 (define_insn "smin<mode>3"
5366   [(set (match_operand:GPF 0 "register_operand" "=w")
5367         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
5368                   (match_operand:GPF 2 "register_operand" "w")))]
5369   "TARGET_FLOAT"
5370   "fminnm\\t%<s>0, %<s>1, %<s>2"
5371   [(set_attr "type" "f_minmax<s>")]
5374 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
5375 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
5376 ;; which implement the IEEE fmax ()/fmin () functions.
5377 (define_insn "<maxmin_uns><mode>3"
5378   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5379         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
5380                      (match_operand:GPF_F16 2 "register_operand" "w")]
5381                      FMAXMIN_UNS))]
5382   "TARGET_FLOAT"
5383   "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
5384   [(set_attr "type" "f_minmax<stype>")]
5387 (define_expand "lrint<GPF:mode><GPI:mode>2"
5388   [(match_operand:GPI 0 "register_operand")
5389    (match_operand:GPF 1 "register_operand")]
5390   "TARGET_FLOAT
5391    && ((GET_MODE_SIZE (<GPF:MODE>mode) <= GET_MODE_SIZE (<GPI:MODE>mode))
5392    || !flag_trapping_math || flag_fp_int_builtin_inexact)"
5394   rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
5395   emit_insn (gen_rint<GPF:mode>2 (cvt, operands[1]));
5396   emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>2 (operands[0], cvt));
5397   DONE;
5401 ;; For copysign (x, y), we want to generate:
5403 ;;   LDR d2, #(1 << 63)
5404 ;;   BSL v2.8b, [y], [x]
5406 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
5407 ;; aarch64_simd_bsldf will select the best suited of these instructions
5408 ;; to generate based on register allocation, and knows how to partially
5409 ;; constant fold based on the values of X and Y, so expand through that.
5411 (define_expand "copysigndf3"
5412   [(match_operand:DF 0 "register_operand")
5413    (match_operand:DF 1 "register_operand")
5414    (match_operand:DF 2 "register_operand")]
5415   "TARGET_FLOAT && TARGET_SIMD"
5417   rtx mask = gen_reg_rtx (DImode);
5418   emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
5419   emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
5420                                      operands[2], operands[1]));
5421   DONE;
5425 ;; As above, but we must first get to a 64-bit value if we wish to use
5426 ;; aarch64_simd_bslv2sf.
5428 (define_expand "copysignsf3"
5429   [(match_operand:SF 0 "register_operand")
5430    (match_operand:SF 1 "register_operand")
5431    (match_operand:SF 2 "register_operand")]
5432   "TARGET_FLOAT && TARGET_SIMD"
5434   rtx v_bitmask = gen_reg_rtx (V2SImode);
5436   /* Juggle modes to get us in to a vector mode for BSL.  */
5437   rtx op1 = lowpart_subreg (DImode, operands[1], SFmode);
5438   rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
5439   rtx tmp = gen_reg_rtx (V2SFmode);
5440   emit_move_insn (v_bitmask,
5441                   aarch64_simd_gen_const_vector_dup (V2SImode,
5442                                                      HOST_WIDE_INT_M1U << 31));
5443   emit_insn (gen_aarch64_simd_bslv2sf (tmp, v_bitmask, op2, op1));
5444   emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
5445   DONE;
5449 ;; For xorsign (x, y), we want to generate:
5451 ;; LDR   d2, #1<<63
5452 ;; AND   v3.8B, v1.8B, v2.8B
5453 ;; EOR   v0.8B, v0.8B, v3.8B
5456 (define_expand "xorsign<mode>3"
5457   [(match_operand:GPF 0 "register_operand")
5458    (match_operand:GPF 1 "register_operand")
5459    (match_operand:GPF 2 "register_operand")]
5460   "TARGET_FLOAT && TARGET_SIMD"
5463   machine_mode imode = <V_INT_EQUIV>mode;
5464   rtx mask = gen_reg_rtx (imode);
5465   rtx op1x = gen_reg_rtx (imode);
5466   rtx op2x = gen_reg_rtx (imode);
5468   int bits = GET_MODE_BITSIZE (<MODE>mode) - 1;
5469   emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
5470                                                      imode)));
5472   emit_insn (gen_and<v_int_equiv>3 (op2x, mask,
5473                                     lowpart_subreg (imode, operands[2],
5474                                                     <MODE>mode)));
5475   emit_insn (gen_xor<v_int_equiv>3 (op1x,
5476                                     lowpart_subreg (imode, operands[1],
5477                                                     <MODE>mode),
5478                                     op2x));
5479   emit_move_insn (operands[0],
5480                   lowpart_subreg (<MODE>mode, op1x, imode));
5481   DONE;
5485 ;; -------------------------------------------------------------------
5486 ;; Reload support
5487 ;; -------------------------------------------------------------------
5488 ;; Reload Scalar Floating point modes from constant pool.
5489 ;; The AArch64 port doesn't have __int128 constant move support.
5490 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5491  [(set (match_operand:GPF_TF 0 "register_operand" "=w")
5492        (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
5493   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5494  "TARGET_FLOAT"
5496    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5497    emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5498    DONE;
5502 ;; Reload Vector modes from constant pool.
5503 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5504  [(set (match_operand:VALL 0 "register_operand" "=w")
5505        (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5506   (clobber (match_operand:P 2 "register_operand" "=&r"))]
5507  "TARGET_FLOAT"
5509    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5510    emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5511    DONE;
5515 (define_expand "aarch64_reload_mov<mode>"
5516   [(set (match_operand:TX 0 "register_operand" "=w")
5517         (match_operand:TX 1 "register_operand" "w"))
5518    (clobber (match_operand:DI 2 "register_operand" "=&r"))
5519   ]
5520   "TARGET_FLOAT"
5521   {
5522     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5523     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5524     gen_aarch64_movtilow_tilow (op0, op1);
5525     gen_aarch64_movdi_tihigh (operands[2], op1);
5526     gen_aarch64_movtihigh_di (op0, operands[2]);
5527     DONE;
5528   }
5531 ;; The following secondary reload helpers patterns are invoked
5532 ;; after or during reload as we don't want these patterns to start
5533 ;; kicking in during the combiner.
5535 (define_insn "aarch64_movdi_<mode>low"
5536   [(set (match_operand:DI 0 "register_operand" "=r")
5537         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5538                          (const_int 64) (const_int 0)))]
5539   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5540   "fmov\\t%x0, %d1"
5541   [(set_attr "type" "f_mrc")
5542    (set_attr "length" "4")
5543   ])
5545 (define_insn "aarch64_movdi_<mode>high"
5546   [(set (match_operand:DI 0 "register_operand" "=r")
5547         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5548                          (const_int 64) (const_int 64)))]
5549   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5550   "fmov\\t%x0, %1.d[1]"
5551   [(set_attr "type" "f_mrc")
5552    (set_attr "length" "4")
5553   ])
5555 (define_insn "aarch64_mov<mode>high_di"
5556   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5557                          (const_int 64) (const_int 64))
5558         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5559   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5560   "fmov\\t%0.d[1], %x1"
5561   [(set_attr "type" "f_mcr")
5562    (set_attr "length" "4")
5563   ])
5565 (define_insn "aarch64_mov<mode>low_di"
5566   [(set (match_operand:TX 0 "register_operand" "=w")
5567         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5568   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5569   "fmov\\t%d0, %x1"
5570   [(set_attr "type" "f_mcr")
5571    (set_attr "length" "4")
5572   ])
5574 (define_insn "aarch64_movtilow_tilow"
5575   [(set (match_operand:TI 0 "register_operand" "=w")
5576         (zero_extend:TI
5577           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5578   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5579   "fmov\\t%d0, %d1"
5580   [(set_attr "type" "fmov")
5581    (set_attr "length" "4")
5582   ])
5584 ;; There is a deliberate reason why the parameters of high and lo_sum's
5585 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
5586 ;; and lo_sum's to be used with the labels defining the jump tables in
5587 ;; rodata section.
5589 (define_expand "add_losym"
5590   [(set (match_operand 0 "register_operand" "=r")
5591         (lo_sum (match_operand 1 "register_operand" "r")
5592                 (match_operand 2 "aarch64_valid_symref" "S")))]
5593   ""
5595   machine_mode mode = GET_MODE (operands[0]);
5597   emit_insn ((mode == DImode
5598               ? gen_add_losym_di
5599               : gen_add_losym_si) (operands[0],
5600                                    operands[1],
5601                                    operands[2]));
5602   DONE;
5605 (define_insn "add_losym_<mode>"
5606   [(set (match_operand:P 0 "register_operand" "=r")
5607         (lo_sum:P (match_operand:P 1 "register_operand" "r")
5608                   (match_operand 2 "aarch64_valid_symref" "S")))]
5609   ""
5610   "add\\t%<w>0, %<w>1, :lo12:%c2"
5611   [(set_attr "type" "alu_imm")]
5614 (define_insn "ldr_got_small_<mode>"
5615   [(set (match_operand:PTR 0 "register_operand" "=r")
5616         (unspec:PTR [(mem:PTR (lo_sum:PTR
5617                               (match_operand:PTR 1 "register_operand" "r")
5618                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5619                     UNSPEC_GOTSMALLPIC))]
5620   ""
5621   "ldr\\t%<w>0, [%1, #:got_lo12:%c2]"
5622   [(set_attr "type" "load_<ldst_sz>")]
5625 (define_insn "ldr_got_small_sidi"
5626   [(set (match_operand:DI 0 "register_operand" "=r")
5627         (zero_extend:DI
5628          (unspec:SI [(mem:SI (lo_sum:DI
5629                              (match_operand:DI 1 "register_operand" "r")
5630                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5631                     UNSPEC_GOTSMALLPIC)))]
5632   "TARGET_ILP32"
5633   "ldr\\t%w0, [%1, #:got_lo12:%c2]"
5634   [(set_attr "type" "load_4")]
5637 (define_insn "ldr_got_small_28k_<mode>"
5638   [(set (match_operand:PTR 0 "register_operand" "=r")
5639         (unspec:PTR [(mem:PTR (lo_sum:PTR
5640                               (match_operand:PTR 1 "register_operand" "r")
5641                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5642                     UNSPEC_GOTSMALLPIC28K))]
5643   ""
5644   "ldr\\t%<w>0, [%1, #:<got_modifier>:%c2]"
5645   [(set_attr "type" "load_<ldst_sz>")]
5648 (define_insn "ldr_got_small_28k_sidi"
5649   [(set (match_operand:DI 0 "register_operand" "=r")
5650         (zero_extend:DI
5651          (unspec:SI [(mem:SI (lo_sum:DI
5652                              (match_operand:DI 1 "register_operand" "r")
5653                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5654                     UNSPEC_GOTSMALLPIC28K)))]
5655   "TARGET_ILP32"
5656   "ldr\\t%w0, [%1, #:gotpage_lo14:%c2]"
5657   [(set_attr "type" "load_4")]
5660 (define_insn "ldr_got_tiny"
5661   [(set (match_operand:DI 0 "register_operand" "=r")
5662         (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5663                    UNSPEC_GOTTINYPIC))]
5664   ""
5665   "ldr\\t%0, %L1"
5666   [(set_attr "type" "load_8")]
5669 (define_insn "aarch64_load_tp_hard"
5670   [(set (match_operand:DI 0 "register_operand" "=r")
5671         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5672   ""
5673   "mrs\\t%0, tpidr_el0"
5674   [(set_attr "type" "mrs")]
5677 ;; The TLS ABI specifically requires that the compiler does not schedule
5678 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5679 ;; Therefore we treat the stubs as an atomic sequence.
5680 (define_expand "tlsgd_small_<mode>"
5681  [(parallel [(set (match_operand 0 "register_operand" "")
5682                   (call (mem:DI (match_dup 2)) (const_int 1)))
5683              (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5684              (clobber (reg:DI LR_REGNUM))])]
5685  ""
5687   operands[2] = aarch64_tls_get_addr ();
5690 (define_insn "*tlsgd_small_<mode>"
5691   [(set (match_operand 0 "register_operand" "")
5692         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5693    (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5694    (clobber (reg:DI LR_REGNUM))
5695   ]
5696   ""
5697   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5698   [(set_attr "type" "call")
5699    (set_attr "length" "16")])
5701 (define_insn "tlsie_small_<mode>"
5702   [(set (match_operand:PTR 0 "register_operand" "=r")
5703         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5704                    UNSPEC_GOTSMALLTLS))]
5705   ""
5706   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5707   [(set_attr "type" "load_4")
5708    (set_attr "length" "8")]
5711 (define_insn "tlsie_small_sidi"
5712   [(set (match_operand:DI 0 "register_operand" "=r")
5713         (zero_extend:DI
5714           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5715                       UNSPEC_GOTSMALLTLS)))]
5716   ""
5717   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5718   [(set_attr "type" "load_4")
5719    (set_attr "length" "8")]
5722 (define_insn "tlsie_tiny_<mode>"
5723   [(set (match_operand:PTR 0 "register_operand" "=&r")
5724         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5725                      (match_operand:PTR 2 "register_operand" "r")]
5726                    UNSPEC_GOTTINYTLS))]
5727   ""
5728   "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5729   [(set_attr "type" "multiple")
5730    (set_attr "length" "8")]
5733 (define_insn "tlsie_tiny_sidi"
5734   [(set (match_operand:DI 0 "register_operand" "=&r")
5735         (zero_extend:DI
5736           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5737                       (match_operand:DI 2 "register_operand" "r")
5738                       ]
5739                       UNSPEC_GOTTINYTLS)))]
5740   ""
5741   "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5742   [(set_attr "type" "multiple")
5743    (set_attr "length" "8")]
5746 (define_insn "tlsle12_<mode>"
5747   [(set (match_operand:P 0 "register_operand" "=r")
5748         (unspec:P [(match_operand:P 1 "register_operand" "r")
5749                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5750                    UNSPEC_TLSLE12))]
5751   ""
5752   "add\\t%<w>0, %<w>1, #%L2";
5753   [(set_attr "type" "alu_sreg")
5754    (set_attr "length" "4")]
5757 (define_insn "tlsle24_<mode>"
5758   [(set (match_operand:P 0 "register_operand" "=r")
5759         (unspec:P [(match_operand:P 1 "register_operand" "r")
5760                    (match_operand 2 "aarch64_tls_le_symref" "S")]
5761                    UNSPEC_TLSLE24))]
5762   ""
5763   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5764   [(set_attr "type" "multiple")
5765    (set_attr "length" "8")]
5768 (define_insn "tlsle32_<mode>"
5769   [(set (match_operand:P 0 "register_operand" "=r")
5770         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5771                    UNSPEC_TLSLE32))]
5772   ""
5773   "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5774   [(set_attr "type" "multiple")
5775    (set_attr "length" "8")]
5778 (define_insn "tlsle48_<mode>"
5779   [(set (match_operand:P 0 "register_operand" "=r")
5780         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5781                    UNSPEC_TLSLE48))]
5782   ""
5783   "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5784   [(set_attr "type" "multiple")
5785    (set_attr "length" "12")]
5788 (define_expand "tlsdesc_small_<mode>"
5789   [(unspec:PTR [(match_operand 0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
5790   "TARGET_TLS_DESC"
5791   {
5792     if (TARGET_SVE)
5793       emit_insn (gen_tlsdesc_small_sve_<mode> (operands[0]));
5794     else
5795       emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
5796     DONE;
5797   }
5800 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
5801 ;; R0 and LR.
5802 (define_insn "tlsdesc_small_advsimd_<mode>"
5803   [(set (reg:PTR R0_REGNUM)
5804         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5805                     UNSPEC_TLSDESC))
5806    (clobber (reg:DI LR_REGNUM))
5807    (clobber (reg:CC CC_REGNUM))
5808    (clobber (match_scratch:DI 1 "=r"))]
5809   "TARGET_TLS_DESC && !TARGET_SVE"
5810   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5811   [(set_attr "type" "call")
5812    (set_attr "length" "16")])
5814 ;; For SVE, model tlsdesc calls as clobbering all vector and predicate
5815 ;; registers, on top of the usual R0 and LR.  In reality the calls
5816 ;; preserve the low 128 bits of the vector registers, but we don't
5817 ;; yet have a way of representing that in the instruction pattern.
5818 (define_insn "tlsdesc_small_sve_<mode>"
5819   [(set (reg:PTR R0_REGNUM)
5820         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5821                     UNSPEC_TLSDESC))
5822    (clobber (reg:DI LR_REGNUM))
5823    (clobber (reg:CC CC_REGNUM))
5824    (clobber (reg:XI V0_REGNUM))
5825    (clobber (reg:XI V4_REGNUM))
5826    (clobber (reg:XI V8_REGNUM))
5827    (clobber (reg:XI V12_REGNUM))
5828    (clobber (reg:XI V16_REGNUM))
5829    (clobber (reg:XI V20_REGNUM))
5830    (clobber (reg:XI V24_REGNUM))
5831    (clobber (reg:XI V28_REGNUM))
5832    (clobber (reg:VNx2BI P0_REGNUM))
5833    (clobber (reg:VNx2BI P1_REGNUM))
5834    (clobber (reg:VNx2BI P2_REGNUM))
5835    (clobber (reg:VNx2BI P3_REGNUM))
5836    (clobber (reg:VNx2BI P4_REGNUM))
5837    (clobber (reg:VNx2BI P5_REGNUM))
5838    (clobber (reg:VNx2BI P6_REGNUM))
5839    (clobber (reg:VNx2BI P7_REGNUM))
5840    (clobber (reg:VNx2BI P8_REGNUM))
5841    (clobber (reg:VNx2BI P9_REGNUM))
5842    (clobber (reg:VNx2BI P10_REGNUM))
5843    (clobber (reg:VNx2BI P11_REGNUM))
5844    (clobber (reg:VNx2BI P12_REGNUM))
5845    (clobber (reg:VNx2BI P13_REGNUM))
5846    (clobber (reg:VNx2BI P14_REGNUM))
5847    (clobber (reg:VNx2BI P15_REGNUM))
5848    (clobber (match_scratch:DI 1 "=r"))]
5849   "TARGET_TLS_DESC && TARGET_SVE"
5850   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5851   [(set_attr "type" "call")
5852    (set_attr "length" "16")])
5854 (define_insn "stack_tie"
5855   [(set (mem:BLK (scratch))
5856         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5857                      (match_operand:DI 1 "register_operand" "rk")]
5858                     UNSPEC_PRLG_STK))]
5859   ""
5860   ""
5861   [(set_attr "length" "0")]
5864 ;; Pointer authentication patterns are always provided.  In architecture
5865 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
5866 ;; This lets the user write portable software which authenticates pointers
5867 ;; when run on something which implements ARMv8.3-A, and which runs
5868 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
5869 ;; implemented.
5871 ;; Signing/Authenticating R30 using SP as the salt.
5873 (define_insn "<pauth_mnem_prefix>sp"
5874   [(set (reg:DI R30_REGNUM)
5875         (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
5876   ""
5877   "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
5880 ;; Signing/Authenticating X17 using X16 as the salt.
5882 (define_insn "<pauth_mnem_prefix>1716"
5883   [(set (reg:DI R17_REGNUM)
5884         (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
5885   ""
5886   "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
5889 ;; Stripping the signature in R30.
5891 (define_insn "xpaclri"
5892   [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
5893   ""
5894   "hint\t7 // xpaclri"
5897 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5898 ;; all of memory.  This blocks insns from being moved across this point.
5900 (define_insn "blockage"
5901   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5902   ""
5903   ""
5904   [(set_attr "length" "0")
5905    (set_attr "type" "block")]
5908 (define_insn "probe_stack_range"
5909   [(set (match_operand:DI 0 "register_operand" "=r")
5910         (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
5911                              (match_operand:DI 2 "register_operand" "r")]
5912                               UNSPECV_PROBE_STACK_RANGE))]
5913   ""
5915   return aarch64_output_probe_stack_range (operands[0], operands[2]);
5917   [(set_attr "length" "32")]
5920 ;; Named pattern for expanding thread pointer reference.
5921 (define_expand "get_thread_pointerdi"
5922   [(match_operand:DI 0 "register_operand" "=r")]
5923   ""
5925   rtx tmp = aarch64_load_tp (operands[0]);
5926   if (tmp != operands[0])
5927     emit_move_insn (operands[0], tmp);
5928   DONE;
5931 ;; Named patterns for stack smashing protection.
5932 (define_expand "stack_protect_set"
5933   [(match_operand 0 "memory_operand")
5934    (match_operand 1 "memory_operand")]
5935   ""
5937   machine_mode mode = GET_MODE (operands[0]);
5939   emit_insn ((mode == DImode
5940               ? gen_stack_protect_set_di
5941               : gen_stack_protect_set_si) (operands[0], operands[1]));
5942   DONE;
5945 (define_insn "stack_protect_set_<mode>"
5946   [(set (match_operand:PTR 0 "memory_operand" "=m")
5947         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5948          UNSPEC_SP_SET))
5949    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5950   ""
5951   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5952   [(set_attr "length" "12")
5953    (set_attr "type" "multiple")])
5955 (define_expand "stack_protect_test"
5956   [(match_operand 0 "memory_operand")
5957    (match_operand 1 "memory_operand")
5958    (match_operand 2)]
5959   ""
5961   rtx result;
5962   machine_mode mode = GET_MODE (operands[0]);
5964   result = gen_reg_rtx(mode);
5966   emit_insn ((mode == DImode
5967               ? gen_stack_protect_test_di
5968               : gen_stack_protect_test_si) (result,
5969                                             operands[0],
5970                                             operands[1]));
5972   if (mode == DImode)
5973     emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5974                                     result, const0_rtx, operands[2]));
5975   else
5976     emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5977                                     result, const0_rtx, operands[2]));
5978   DONE;
5981 (define_insn "stack_protect_test_<mode>"
5982   [(set (match_operand:PTR 0 "register_operand" "=r")
5983         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5984                      (match_operand:PTR 2 "memory_operand" "m")]
5985          UNSPEC_SP_TEST))
5986    (clobber (match_scratch:PTR 3 "=&r"))]
5987   ""
5988   "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5989   [(set_attr "length" "12")
5990    (set_attr "type" "multiple")])
5992 ;; Write Floating-point Control Register.
5993 (define_insn "set_fpcr"
5994   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5995   ""
5996   "msr\\tfpcr, %0"
5997   [(set_attr "type" "mrs")])
5999 ;; Read Floating-point Control Register.
6000 (define_insn "get_fpcr"
6001   [(set (match_operand:SI 0 "register_operand" "=r")
6002         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
6003   ""
6004   "mrs\\t%0, fpcr"
6005   [(set_attr "type" "mrs")])
6007 ;; Write Floating-point Status Register.
6008 (define_insn "set_fpsr"
6009   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
6010   ""
6011   "msr\\tfpsr, %0"
6012   [(set_attr "type" "mrs")])
6014 ;; Read Floating-point Status Register.
6015 (define_insn "get_fpsr"
6016   [(set (match_operand:SI 0 "register_operand" "=r")
6017         (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
6018   ""
6019   "mrs\\t%0, fpsr"
6020   [(set_attr "type" "mrs")])
6023 ;; Define the subtract-one-and-jump insns so loop.c
6024 ;; knows what to generate.
6025 (define_expand "doloop_end"
6026   [(use (match_operand 0 "" ""))      ; loop pseudo
6027    (use (match_operand 1 "" ""))]     ; label
6028   "optimize > 0 && flag_modulo_sched"
6030   rtx s0;
6031   rtx bcomp;
6032   rtx loc_ref;
6033   rtx cc_reg;
6034   rtx insn;
6035   rtx cmp;
6037   /* Currently SMS relies on the do-loop pattern to recognize loops
6038      where (1) the control part consists of all insns defining and/or
6039      using a certain 'count' register and (2) the loop count can be
6040      adjusted by modifying this register prior to the loop.
6041      ??? The possible introduction of a new block to initialize the
6042      new IV can potentially affect branch optimizations.  */
6044   if (GET_MODE (operands[0]) != DImode)
6045     FAIL;
6047   s0 = operands [0];
6048   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
6050   cmp = XVECEXP (PATTERN (insn), 0, 0);
6051   cc_reg = SET_DEST (cmp);
6052   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
6053   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
6054   emit_jump_insn (gen_rtx_SET (pc_rtx,
6055                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
6056                                                      loc_ref, pc_rtx)));
6057   DONE;
6060 ;; Helper for aarch64.c code.
6061 (define_expand "set_clobber_cc"
6062   [(parallel [(set (match_operand 0)
6063                    (match_operand 1))
6064               (clobber (reg:CC CC_REGNUM))])])
6066 ;; AdvSIMD Stuff
6067 (include "aarch64-simd.md")
6069 ;; Atomic Operations
6070 (include "atomics.md")
6072 ;; ldp/stp peephole patterns
6073 (include "aarch64-ldpstp.md")
6075 ;; SVE.
6076 (include "aarch64-sve.md")