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