Daily bump.
[gcc.git] / gcc / config / aarch64 / aarch64.md
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2021 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 (R17_REGNUM 17)
42 (R18_REGNUM 18)
43 (R19_REGNUM 19)
44 (R20_REGNUM 20)
45 (R21_REGNUM 21)
46 (R22_REGNUM 22)
47 (R23_REGNUM 23)
48 (R24_REGNUM 24)
49 (R25_REGNUM 25)
50 (R26_REGNUM 26)
51 (R27_REGNUM 27)
52 (R28_REGNUM 28)
53 (R29_REGNUM 29)
54 (R30_REGNUM 30)
55 (SP_REGNUM 31)
56 (V0_REGNUM 32)
57 (V1_REGNUM 33)
58 (V2_REGNUM 34)
59 (V3_REGNUM 35)
60 (V4_REGNUM 36)
61 (V5_REGNUM 37)
62 (V6_REGNUM 38)
63 (V7_REGNUM 39)
64 (V8_REGNUM 40)
65 (V9_REGNUM 41)
66 (V10_REGNUM 42)
67 (V11_REGNUM 43)
68 (V12_REGNUM 44)
69 (V13_REGNUM 45)
70 (V14_REGNUM 46)
71 (V15_REGNUM 47)
72 (V16_REGNUM 48)
73 (V17_REGNUM 49)
74 (V18_REGNUM 50)
75 (V19_REGNUM 51)
76 (V20_REGNUM 52)
77 (V21_REGNUM 53)
78 (V22_REGNUM 54)
79 (V23_REGNUM 55)
80 (V24_REGNUM 56)
81 (V25_REGNUM 57)
82 (V26_REGNUM 58)
83 (V27_REGNUM 59)
84 (V28_REGNUM 60)
85 (V29_REGNUM 61)
86 (V30_REGNUM 62)
87 (V31_REGNUM 63)
88 (SFP_REGNUM 64)
89 (AP_REGNUM 65)
90 (CC_REGNUM 66)
91 ;; Defined only to make the DWARF description simpler.
92 (VG_REGNUM 67)
93 (P0_REGNUM 68)
94 (P1_REGNUM 69)
95 (P2_REGNUM 70)
96 (P3_REGNUM 71)
97 (P4_REGNUM 72)
98 (P5_REGNUM 73)
99 (P6_REGNUM 74)
100 (P7_REGNUM 75)
101 (P8_REGNUM 76)
102 (P9_REGNUM 77)
103 (P10_REGNUM 78)
104 (P11_REGNUM 79)
105 (P12_REGNUM 80)
106 (P13_REGNUM 81)
107 (P14_REGNUM 82)
108 (P15_REGNUM 83)
109 (LAST_SAVED_REGNUM 83)
110 (FFR_REGNUM 84)
111 ;; "FFR token": a fake register used for representing the scheduling
112 ;; restrictions on FFR-related operations.
113 (FFRT_REGNUM 85)
114 ;; The pair of scratch registers used for stack probing with -fstack-check.
115 ;; Leave R9 alone as a possible choice for the static chain.
116 ;; Note that the use of these registers is mutually exclusive with the use
117 ;; of STACK_CLASH_SVE_CFA_REGNUM, which is for -fstack-clash-protection
118 ;; rather than -fstack-check.
119 (PROBE_STACK_FIRST_REGNUM 10)
120 (PROBE_STACK_SECOND_REGNUM 11)
121 ;; Scratch register used by stack clash protection to calculate
122 ;; SVE CFA offsets during probing.
123 (STACK_CLASH_SVE_CFA_REGNUM 11)
124 ;; Scratch registers for prologue/epilogue use.
125 (EP0_REGNUM 12)
126 (EP1_REGNUM 13)
127 ;; A couple of call-clobbered registers that we need to reserve when
128 ;; tracking speculation this is not ABI, so is subject to change.
129 (SPECULATION_SCRATCH_REGNUM 14)
130 (SPECULATION_TRACKER_REGNUM 15)
131 ;; Scratch registers used in frame layout.
132 (IP0_REGNUM 16)
133 (IP1_REGNUM 17)
134 (FP_REGNUM 29)
135 (LR_REGNUM 30)
136 ]
137 )
138
139 (define_c_enum "unspec" [
140 UNSPEC_AUTIA1716
141 UNSPEC_AUTIB1716
142 UNSPEC_AUTIASP
143 UNSPEC_AUTIBSP
144 UNSPEC_CALLEE_ABI
145 UNSPEC_CASESI
146 UNSPEC_CRC32B
147 UNSPEC_CRC32CB
148 UNSPEC_CRC32CH
149 UNSPEC_CRC32CW
150 UNSPEC_CRC32CX
151 UNSPEC_CRC32H
152 UNSPEC_CRC32W
153 UNSPEC_CRC32X
154 UNSPEC_FCVTZS
155 UNSPEC_FCVTZU
156 UNSPEC_FJCVTZS
157 UNSPEC_FRINT32Z
158 UNSPEC_FRINT32X
159 UNSPEC_FRINT64Z
160 UNSPEC_FRINT64X
161 UNSPEC_URECPE
162 UNSPEC_FRECPE
163 UNSPEC_FRECPS
164 UNSPEC_FRECPX
165 UNSPEC_FRINTA
166 UNSPEC_FRINTI
167 UNSPEC_FRINTM
168 UNSPEC_FRINTN
169 UNSPEC_FRINTP
170 UNSPEC_FRINTX
171 UNSPEC_FRINTZ
172 UNSPEC_GOTSMALLPIC
173 UNSPEC_GOTSMALLPIC28K
174 UNSPEC_GOTSMALLTLS
175 UNSPEC_GOTTINYPIC
176 UNSPEC_GOTTINYTLS
177 UNSPEC_LD1
178 UNSPEC_LD2
179 UNSPEC_LD2_DREG
180 UNSPEC_LD2_DUP
181 UNSPEC_LD3
182 UNSPEC_LD3_DREG
183 UNSPEC_LD3_DUP
184 UNSPEC_LD4
185 UNSPEC_LD4_DREG
186 UNSPEC_LD4_DUP
187 UNSPEC_LD2_LANE
188 UNSPEC_LD3_LANE
189 UNSPEC_LD4_LANE
190 UNSPEC_MB
191 UNSPEC_NOP
192 UNSPEC_PACIA1716
193 UNSPEC_PACIB1716
194 UNSPEC_PACIASP
195 UNSPEC_PACIBSP
196 UNSPEC_PRLG_STK
197 UNSPEC_REV
198 UNSPEC_RBIT
199 UNSPEC_SABAL
200 UNSPEC_SABDL2
201 UNSPEC_SADALP
202 UNSPEC_SCVTF
203 UNSPEC_SISD_NEG
204 UNSPEC_SISD_SSHL
205 UNSPEC_SISD_USHL
206 UNSPEC_SSHL_2S
207 UNSPEC_ST1
208 UNSPEC_ST2
209 UNSPEC_ST3
210 UNSPEC_ST4
211 UNSPEC_ST2_LANE
212 UNSPEC_ST3_LANE
213 UNSPEC_ST4_LANE
214 UNSPEC_TLS
215 UNSPEC_TLSDESC
216 UNSPEC_TLSLE12
217 UNSPEC_TLSLE24
218 UNSPEC_TLSLE32
219 UNSPEC_TLSLE48
220 UNSPEC_UABAL
221 UNSPEC_UABDL2
222 UNSPEC_UADALP
223 UNSPEC_UCVTF
224 UNSPEC_USHL_2S
225 UNSPEC_VSTRUCTDUMMY
226 UNSPEC_SSP_SYSREG
227 UNSPEC_SP_SET
228 UNSPEC_SP_TEST
229 UNSPEC_RSQRT
230 UNSPEC_RSQRTE
231 UNSPEC_RSQRTS
232 UNSPEC_NZCV
233 UNSPEC_XPACLRI
234 UNSPEC_LD1_SVE
235 UNSPEC_ST1_SVE
236 UNSPEC_LDNT1_SVE
237 UNSPEC_STNT1_SVE
238 UNSPEC_LD1RQ
239 UNSPEC_LD1_GATHER
240 UNSPEC_LDFF1_GATHER
241 UNSPEC_LDNT1_GATHER
242 UNSPEC_ST1_SCATTER
243 UNSPEC_STNT1_SCATTER
244 UNSPEC_PRED_X
245 UNSPEC_PRED_Z
246 UNSPEC_PTEST
247 UNSPEC_PTRUE
248 UNSPEC_UNPACKSHI
249 UNSPEC_UNPACKUHI
250 UNSPEC_UNPACKSLO
251 UNSPEC_UNPACKULO
252 UNSPEC_PACK
253 UNSPEC_WHILEGE
254 UNSPEC_WHILEGT
255 UNSPEC_WHILEHI
256 UNSPEC_WHILEHS
257 UNSPEC_WHILELE
258 UNSPEC_WHILELO
259 UNSPEC_WHILELS
260 UNSPEC_WHILELT
261 UNSPEC_WHILERW
262 UNSPEC_WHILEWR
263 UNSPEC_LDN
264 UNSPEC_STN
265 UNSPEC_INSR
266 UNSPEC_CLASTA
267 UNSPEC_CLASTB
268 UNSPEC_FADDA
269 UNSPEC_REV_SUBREG
270 UNSPEC_REINTERPRET
271 UNSPEC_SPECULATION_TRACKER
272 UNSPEC_SPECULATION_TRACKER_REV
273 UNSPEC_COPYSIGN
274 UNSPEC_TTEST ; Represent transaction test.
275 UNSPEC_UPDATE_FFR
276 UNSPEC_UPDATE_FFRT
277 UNSPEC_RDFFR
278 UNSPEC_WRFFR
279 ;; Represents an SVE-style lane index, in which the indexing applies
280 ;; within the containing 128-bit block.
281 UNSPEC_SVE_LANE_SELECT
282 UNSPEC_SVE_CNT_PAT
283 UNSPEC_SVE_PREFETCH
284 UNSPEC_SVE_PREFETCH_GATHER
285 UNSPEC_SVE_COMPACT
286 UNSPEC_SVE_SPLICE
287 UNSPEC_GEN_TAG ; Generate a 4-bit MTE tag.
288 UNSPEC_GEN_TAG_RND ; Generate a random 4-bit MTE tag.
289 UNSPEC_TAG_SPACE ; Translate address to MTE tag address space.
290 UNSPEC_LD1RO
291 UNSPEC_SALT_ADDR
292 ])
293
294 (define_c_enum "unspecv" [
295 UNSPECV_EH_RETURN ; Represent EH_RETURN
296 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
297 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
298 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
299 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
300 UNSPECV_BLOCKAGE ; Represent a blockage
301 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
302 UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
303 UNSPECV_BTI_NOARG ; Represent BTI.
304 UNSPECV_BTI_C ; Represent BTI c.
305 UNSPECV_BTI_J ; Represent BTI j.
306 UNSPECV_BTI_JC ; Represent BTI jc.
307 UNSPECV_TSTART ; Represent transaction start.
308 UNSPECV_TCOMMIT ; Represent transaction commit.
309 UNSPECV_TCANCEL ; Represent transaction cancel.
310 UNSPEC_RNDR ; Represent RNDR
311 UNSPEC_RNDRRS ; Represent RNDRRS
312 ]
313 )
314
315 ;; These constants are used as a const_int in various SVE unspecs
316 ;; to indicate whether the governing predicate is known to be a PTRUE.
317 (define_constants
318 [; Indicates that the predicate might not be a PTRUE.
319 (SVE_MAYBE_NOT_PTRUE 0)
320
321 ; Indicates that the predicate is known to be a PTRUE.
322 (SVE_KNOWN_PTRUE 1)])
323
324 ;; These constants are used as a const_int in predicated SVE FP arithmetic
325 ;; to indicate whether the operation is allowed to make additional lanes
326 ;; active without worrying about the effect on faulting behavior.
327 (define_constants
328 [; Indicates either that all lanes are active or that the instruction may
329 ; operate on inactive inputs even if doing so could induce a fault.
330 (SVE_RELAXED_GP 0)
331
332 ; Indicates that some lanes might be inactive and that the instruction
333 ; must not operate on inactive inputs if doing so could induce a fault.
334 (SVE_STRICT_GP 1)])
335
336 ;; If further include files are added the defintion of MD_INCLUDES
337 ;; must be updated.
338
339 (include "constraints.md")
340 (include "predicates.md")
341 (include "iterators.md")
342
343 ;; -------------------------------------------------------------------
344 ;; Instruction types and attributes
345 ;; -------------------------------------------------------------------
346
347 ; The "type" attribute is included here from AArch32 backend to be able
348 ; to share pipeline descriptions.
349 (include "../arm/types.md")
350
351 ;; It is important to set the fp or simd attributes to yes when a pattern
352 ;; alternative uses the FP or SIMD register files, usually signified by use of
353 ;; the 'w' constraint. This will ensure that the alternative will be
354 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
355 ;; architecture extensions. If all the alternatives in a pattern use the
356 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
357 ;; or TARGET_SIMD.
358
359 ;; Attributes of the architecture required to support the instruction (or
360 ;; alternative). This attribute is used to compute attribute "enabled", use type
361 ;; "any" to enable an alternative in all cases.
362
363 (define_enum "arches" [ any rcpc8_4 fp simd sve fp16])
364
365 (define_enum_attr "arch" "arches" (const_string "any"))
366
367 ;; [For compatibility with Arm in pipeline models]
368 ;; Attribute that specifies whether or not the instruction touches fp
369 ;; registers.
370 ;; Note that this attribute is not used anywhere in either the arm or aarch64
371 ;; backends except in the scheduling description for xgene1. In that
372 ;; scheduling description this attribute is used to subclass the load_4 and
373 ;; load_8 types.
374 (define_attr "fp" "no,yes"
375 (if_then_else
376 (eq_attr "arch" "fp")
377 (const_string "yes")
378 (const_string "no")))
379
380 (define_attr "arch_enabled" "no,yes"
381 (if_then_else
382 (ior
383 (eq_attr "arch" "any")
384
385 (and (eq_attr "arch" "rcpc8_4")
386 (match_test "AARCH64_ISA_RCPC8_4"))
387
388 (and (eq_attr "arch" "fp")
389 (match_test "TARGET_FLOAT"))
390
391 (and (eq_attr "arch" "simd")
392 (match_test "TARGET_SIMD"))
393
394 (and (eq_attr "arch" "fp16")
395 (match_test "TARGET_FP_F16INST"))
396
397 (and (eq_attr "arch" "sve")
398 (match_test "TARGET_SVE")))
399 (const_string "yes")
400 (const_string "no")))
401
402 ;; Attribute that controls whether an alternative is enabled or not.
403 ;; Currently it is only used to disable alternatives which touch fp or simd
404 ;; registers when -mgeneral-regs-only is specified or to require a special
405 ;; architecture support.
406 (define_attr "enabled" "no,yes" (attr "arch_enabled"))
407
408 ;; Attribute that specifies whether we are dealing with a branch to a
409 ;; label that is far away, i.e. further away than the maximum/minimum
410 ;; representable in a signed 21-bits number.
411 ;; 0 :=: no
412 ;; 1 :=: yes
413 (define_attr "far_branch" "" (const_int 0))
414
415 ;; Attribute that specifies whether the alternative uses MOVPRFX.
416 (define_attr "movprfx" "no,yes" (const_string "no"))
417
418 ;; Attribute to specify that an alternative has the length of a single
419 ;; instruction plus a speculation barrier.
420 (define_attr "sls_length" "none,retbr,casesi" (const_string "none"))
421
422 (define_attr "length" ""
423 (cond [(eq_attr "movprfx" "yes")
424 (const_int 8)
425
426 (eq_attr "sls_length" "retbr")
427 (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 4)
428 (match_test "TARGET_SB") (const_int 8)]
429 (const_int 12))
430
431 (eq_attr "sls_length" "casesi")
432 (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 16)
433 (match_test "TARGET_SB") (const_int 20)]
434 (const_int 24))
435 ]
436 (const_int 4)))
437
438 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
439 ;; no predicated insns.
440 (define_attr "predicated" "yes,no" (const_string "no"))
441
442 ;; Set to true on an insn that requires the speculation tracking state to be
443 ;; in the tracking register before the insn issues. Otherwise the compiler
444 ;; may chose to hold the tracking state encoded in SP.
445 (define_attr "speculation_barrier" "true,false" (const_string "false"))
446
447 ;; -------------------------------------------------------------------
448 ;; Pipeline descriptions and scheduling
449 ;; -------------------------------------------------------------------
450
451 ;; Processor types.
452 (include "aarch64-tune.md")
453
454 ;; Scheduling
455 (include "../arm/cortex-a53.md")
456 (include "../arm/cortex-a57.md")
457 (include "../arm/exynos-m1.md")
458 (include "falkor.md")
459 (include "saphira.md")
460 (include "thunderx.md")
461 (include "../arm/xgene1.md")
462 (include "thunderx2t99.md")
463 (include "tsv110.md")
464 (include "thunderx3t110.md")
465
466 ;; -------------------------------------------------------------------
467 ;; Jumps and other miscellaneous insns
468 ;; -------------------------------------------------------------------
469
470 (define_insn "indirect_jump"
471 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
472 ""
473 {
474 output_asm_insn ("br\\t%0", operands);
475 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
476 }
477 [(set_attr "type" "branch")
478 (set_attr "sls_length" "retbr")]
479 )
480
481 (define_insn "jump"
482 [(set (pc) (label_ref (match_operand 0 "" "")))]
483 ""
484 "b\\t%l0"
485 [(set_attr "type" "branch")]
486 )
487
488 (define_expand "cbranch<mode>4"
489 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
490 [(match_operand:GPI 1 "register_operand")
491 (match_operand:GPI 2 "aarch64_plus_operand")])
492 (label_ref (match_operand 3 "" ""))
493 (pc)))]
494 ""
495 "
496 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
497 operands[2]);
498 operands[2] = const0_rtx;
499 "
500 )
501
502 (define_expand "cbranch<mode>4"
503 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
504 [(match_operand:GPF 1 "register_operand")
505 (match_operand:GPF 2 "aarch64_fp_compare_operand")])
506 (label_ref (match_operand 3 "" ""))
507 (pc)))]
508 ""
509 "
510 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
511 operands[2]);
512 operands[2] = const0_rtx;
513 "
514 )
515
516 (define_expand "cbranchcc4"
517 [(set (pc) (if_then_else
518 (match_operator 0 "aarch64_comparison_operator"
519 [(match_operand 1 "cc_register")
520 (match_operand 2 "const0_operand")])
521 (label_ref (match_operand 3 "" ""))
522 (pc)))]
523 ""
524 "")
525
526 (define_insn "@ccmp<CC_ONLY:mode><GPI:mode>"
527 [(set (match_operand:CC_ONLY 1 "cc_register" "")
528 (if_then_else:CC_ONLY
529 (match_operator 4 "aarch64_comparison_operator"
530 [(match_operand 0 "cc_register" "")
531 (const_int 0)])
532 (compare:CC_ONLY
533 (match_operand:GPI 2 "register_operand" "r,r,r")
534 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
535 (unspec:CC_ONLY
536 [(match_operand 5 "immediate_operand")]
537 UNSPEC_NZCV)))]
538 ""
539 "@
540 ccmp\\t%<w>2, %<w>3, %k5, %m4
541 ccmp\\t%<w>2, %3, %k5, %m4
542 ccmn\\t%<w>2, #%n3, %k5, %m4"
543 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
544 )
545
546 (define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>"
547 [(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
548 (if_then_else:CCFP_CCFPE
549 (match_operator 4 "aarch64_comparison_operator"
550 [(match_operand 0 "cc_register" "")
551 (const_int 0)])
552 (compare:CCFP_CCFPE
553 (match_operand:GPF 2 "register_operand" "w")
554 (match_operand:GPF 3 "register_operand" "w"))
555 (unspec:CCFP_CCFPE
556 [(match_operand 5 "immediate_operand")]
557 UNSPEC_NZCV)))]
558 "TARGET_FLOAT"
559 "fccmp<e>\\t%<s>2, %<s>3, %k5, %m4"
560 [(set_attr "type" "fccmp<s>")]
561 )
562
563 (define_insn "@ccmp<CC_ONLY:mode><GPI:mode>_rev"
564 [(set (match_operand:CC_ONLY 1 "cc_register" "")
565 (if_then_else:CC_ONLY
566 (match_operator 4 "aarch64_comparison_operator"
567 [(match_operand 0 "cc_register" "")
568 (const_int 0)])
569 (unspec:CC_ONLY
570 [(match_operand 5 "immediate_operand")]
571 UNSPEC_NZCV)
572 (compare:CC_ONLY
573 (match_operand:GPI 2 "register_operand" "r,r,r")
574 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))))]
575 ""
576 "@
577 ccmp\\t%<w>2, %<w>3, %k5, %M4
578 ccmp\\t%<w>2, %3, %k5, %M4
579 ccmn\\t%<w>2, #%n3, %k5, %M4"
580 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
581 )
582
583 (define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>_rev"
584 [(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
585 (if_then_else:CCFP_CCFPE
586 (match_operator 4 "aarch64_comparison_operator"
587 [(match_operand 0 "cc_register" "")
588 (const_int 0)])
589 (unspec:CCFP_CCFPE
590 [(match_operand 5 "immediate_operand")]
591 UNSPEC_NZCV)
592 (compare:CCFP_CCFPE
593 (match_operand:GPF 2 "register_operand" "w")
594 (match_operand:GPF 3 "register_operand" "w"))))]
595 "TARGET_FLOAT"
596 "fccmp<e>\\t%<s>2, %<s>3, %k5, %M4"
597 [(set_attr "type" "fccmp<s>")]
598 )
599
600 ;; Expansion of signed mod by a power of 2 using CSNEG.
601 ;; For x0 % n where n is a power of 2 produce:
602 ;; negs x1, x0
603 ;; and x0, x0, #(n - 1)
604 ;; and x1, x1, #(n - 1)
605 ;; csneg x0, x0, x1, mi
606
607 (define_expand "mod<mode>3"
608 [(match_operand:GPI 0 "register_operand")
609 (match_operand:GPI 1 "register_operand")
610 (match_operand:GPI 2 "const_int_operand")]
611 ""
612 {
613 HOST_WIDE_INT val = INTVAL (operands[2]);
614
615 if (val <= 0
616 || exact_log2 (val) <= 0
617 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
618 FAIL;
619
620 rtx mask = GEN_INT (val - 1);
621
622 /* In the special case of x0 % 2 we can do the even shorter:
623 cmp x0, xzr
624 and x0, x0, 1
625 cneg x0, x0, lt. */
626 if (val == 2)
627 {
628 rtx masked = gen_reg_rtx (<MODE>mode);
629 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
630 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
631 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
632 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
633 DONE;
634 }
635
636 rtx neg_op = gen_reg_rtx (<MODE>mode);
637 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
638
639 /* Extract the condition register and mode. */
640 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
641 rtx cc_reg = SET_DEST (cmp);
642 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
643
644 rtx masked_pos = gen_reg_rtx (<MODE>mode);
645 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
646
647 rtx masked_neg = gen_reg_rtx (<MODE>mode);
648 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
649
650 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
651 masked_neg, masked_pos));
652 DONE;
653 }
654 )
655
656 (define_insn "condjump"
657 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
658 [(match_operand 1 "cc_register" "") (const_int 0)])
659 (label_ref (match_operand 2 "" ""))
660 (pc)))]
661 ""
662 {
663 /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
664 but the "." is required for SVE conditions. */
665 bool use_dot_p = GET_MODE (operands[1]) == CC_NZCmode;
666 if (get_attr_length (insn) == 8)
667 return aarch64_gen_far_branch (operands, 2, "Lbcond",
668 use_dot_p ? "b.%M0\\t" : "b%M0\\t");
669 else
670 return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
671 }
672 [(set_attr "type" "branch")
673 (set (attr "length")
674 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
675 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
676 (const_int 4)
677 (const_int 8)))
678 (set (attr "far_branch")
679 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
680 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
681 (const_int 0)
682 (const_int 1)))]
683 )
684
685 ;; For a 24-bit immediate CST we can optimize the compare for equality
686 ;; and branch sequence from:
687 ;; mov x0, #imm1
688 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
689 ;; cmp x1, x0
690 ;; b<ne,eq> .Label
691 ;; into the shorter:
692 ;; sub x0, x1, #(CST & 0xfff000)
693 ;; subs x0, x0, #(CST & 0x000fff)
694 ;; b<ne,eq> .Label
695 (define_insn_and_split "*compare_condjump<GPI:mode>"
696 [(set (pc) (if_then_else (EQL
697 (match_operand:GPI 0 "register_operand" "r")
698 (match_operand:GPI 1 "aarch64_imm24" "n"))
699 (label_ref:P (match_operand 2 "" ""))
700 (pc)))]
701 "!aarch64_move_imm (INTVAL (operands[1]), <GPI:MODE>mode)
702 && !aarch64_plus_operand (operands[1], <GPI:MODE>mode)
703 && !reload_completed"
704 "#"
705 "&& true"
706 [(const_int 0)]
707 {
708 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
709 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
710 rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
711 emit_insn (gen_add<GPI:mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
712 emit_insn (gen_add<GPI:mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
713 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
714 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
715 cc_reg, const0_rtx);
716 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
717 DONE;
718 }
719 )
720
721 (define_expand "casesi"
722 [(match_operand:SI 0 "register_operand") ; Index
723 (match_operand:SI 1 "const_int_operand") ; Lower bound
724 (match_operand:SI 2 "const_int_operand") ; Total range
725 (match_operand:DI 3 "" "") ; Table label
726 (match_operand:DI 4 "" "")] ; Out of range label
727 ""
728 {
729 if (operands[1] != const0_rtx)
730 {
731 rtx reg = gen_reg_rtx (SImode);
732
733 /* Canonical RTL says that if you have:
734
735 (minus (X) (CONST))
736
737 then this should be emitted as:
738
739 (plus (X) (-CONST))
740
741 The use of trunc_int_for_mode ensures that the resulting
742 constant can be represented in SImode, this is important
743 for the corner case where operand[1] is INT_MIN. */
744
745 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
746
747 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
748 (operands[1], SImode))
749 operands[1] = force_reg (SImode, operands[1]);
750 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
751 operands[0] = reg;
752 }
753
754 if (!aarch64_plus_operand (operands[2], SImode))
755 operands[2] = force_reg (SImode, operands[2]);
756 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
757 const0_rtx),
758 operands[0], operands[2], operands[4]));
759
760 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3]));
761 operands[2]
762 = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], operands[0]),
763 UNSPEC_CASESI);
764 operands[2] = gen_rtx_MEM (DImode, operands[2]);
765 MEM_READONLY_P (operands[2]) = 1;
766 MEM_NOTRAP_P (operands[2]) = 1;
767 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[3]));
768 DONE;
769 }
770 )
771
772 (define_expand "casesi_dispatch"
773 [(parallel
774 [(set (pc) (match_operand:DI 0 ""))
775 (clobber (reg:CC CC_REGNUM))
776 (clobber (match_scratch:DI 2))
777 (clobber (match_scratch:DI 3))
778 (use (label_ref:DI (match_operand 1 "")))])]
779 "")
780
781 (define_insn "*casesi_dispatch"
782 [(parallel
783 [(set (pc)
784 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
785 (match_operand:SI 1 "register_operand" "r")]
786 UNSPEC_CASESI)))
787 (clobber (reg:CC CC_REGNUM))
788 (clobber (match_scratch:DI 3 "=r"))
789 (clobber (match_scratch:DI 4 "=r"))
790 (use (label_ref:DI (match_operand 2 "" "")))])]
791 ""
792 "*
793 return aarch64_output_casesi (operands);
794 "
795 [(set_attr "sls_length" "casesi")
796 (set_attr "type" "branch")]
797 )
798
799 (define_insn "nop"
800 [(unspec[(const_int 0)] UNSPEC_NOP)]
801 ""
802 "nop"
803 [(set_attr "type" "no_insn")]
804 )
805
806 (define_insn "prefetch"
807 [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
808 (match_operand:QI 1 "const_int_operand" "")
809 (match_operand:QI 2 "const_int_operand" ""))]
810 ""
811 {
812 const char * pftype[2][4] =
813 {
814 {"prfm\\tPLDL1STRM, %0",
815 "prfm\\tPLDL3KEEP, %0",
816 "prfm\\tPLDL2KEEP, %0",
817 "prfm\\tPLDL1KEEP, %0"},
818 {"prfm\\tPSTL1STRM, %0",
819 "prfm\\tPSTL3KEEP, %0",
820 "prfm\\tPSTL2KEEP, %0",
821 "prfm\\tPSTL1KEEP, %0"},
822 };
823
824 int locality = INTVAL (operands[2]);
825
826 gcc_assert (IN_RANGE (locality, 0, 3));
827
828 /* PRFM accepts the same addresses as a 64-bit LDR so wrap
829 the address into a DImode MEM so that aarch64_print_operand knows
830 how to print it. */
831 operands[0] = gen_rtx_MEM (DImode, operands[0]);
832 return pftype[INTVAL(operands[1])][locality];
833 }
834 [(set_attr "type" "load_4")]
835 )
836
837 (define_insn "trap"
838 [(trap_if (const_int 1) (const_int 8))]
839 ""
840 "brk #1000"
841 [(set_attr "type" "trap")])
842
843 (define_expand "prologue"
844 [(clobber (const_int 0))]
845 ""
846 "
847 aarch64_expand_prologue ();
848 DONE;
849 "
850 )
851
852 (define_expand "epilogue"
853 [(clobber (const_int 0))]
854 ""
855 "
856 aarch64_expand_epilogue (false);
857 DONE;
858 "
859 )
860
861 (define_expand "sibcall_epilogue"
862 [(clobber (const_int 0))]
863 ""
864 "
865 aarch64_expand_epilogue (true);
866 DONE;
867 "
868 )
869
870 (define_insn "*do_return"
871 [(return)]
872 ""
873 {
874 const char *ret = NULL;
875 if (aarch64_return_address_signing_enabled ()
876 && (TARGET_PAUTH)
877 && !crtl->calls_eh_return)
878 {
879 if (aarch64_ra_sign_key == AARCH64_KEY_B)
880 ret = "retab";
881 else
882 ret = "retaa";
883 }
884 else
885 ret = "ret";
886 output_asm_insn (ret, operands);
887 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
888 }
889 [(set_attr "type" "branch")
890 (set_attr "sls_length" "retbr")]
891 )
892
893 (define_expand "return"
894 [(simple_return)]
895 "aarch64_use_return_insn_p ()"
896 ""
897 )
898
899 (define_insn "simple_return"
900 [(simple_return)]
901 ""
902 {
903 output_asm_insn ("ret", operands);
904 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
905 }
906 [(set_attr "type" "branch")
907 (set_attr "sls_length" "retbr")]
908 )
909
910 (define_insn "*cb<optab><mode>1"
911 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
912 (const_int 0))
913 (label_ref (match_operand 1 "" ""))
914 (pc)))]
915 "!aarch64_track_speculation"
916 {
917 if (get_attr_length (insn) == 8)
918 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
919 else
920 return "<cbz>\\t%<w>0, %l1";
921 }
922 [(set_attr "type" "branch")
923 (set (attr "length")
924 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
925 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
926 (const_int 4)
927 (const_int 8)))
928 (set (attr "far_branch")
929 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
930 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
931 (const_int 0)
932 (const_int 1)))]
933 )
934
935 (define_insn "*tb<optab><mode>1"
936 [(set (pc) (if_then_else
937 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
938 (const_int 1)
939 (match_operand 1
940 "aarch64_simd_shift_imm_<mode>" "n"))
941 (const_int 0))
942 (label_ref (match_operand 2 "" ""))
943 (pc)))
944 (clobber (reg:CC CC_REGNUM))]
945 "!aarch64_track_speculation"
946 {
947 if (get_attr_length (insn) == 8)
948 {
949 if (get_attr_far_branch (insn) == 1)
950 return aarch64_gen_far_branch (operands, 2, "Ltb",
951 "<inv_tb>\\t%<w>0, %1, ");
952 else
953 {
954 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
955 return "tst\t%<w>0, %1\;<bcond>\t%l2";
956 }
957 }
958 else
959 return "<tbz>\t%<w>0, %1, %l2";
960 }
961 [(set_attr "type" "branch")
962 (set (attr "length")
963 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
964 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
965 (const_int 4)
966 (const_int 8)))
967 (set (attr "far_branch")
968 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
969 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
970 (const_int 0)
971 (const_int 1)))]
972
973 )
974
975 (define_insn "*cb<optab><mode>1"
976 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
977 (const_int 0))
978 (label_ref (match_operand 1 "" ""))
979 (pc)))
980 (clobber (reg:CC CC_REGNUM))]
981 "!aarch64_track_speculation"
982 {
983 if (get_attr_length (insn) == 8)
984 {
985 if (get_attr_far_branch (insn) == 1)
986 return aarch64_gen_far_branch (operands, 1, "Ltb",
987 "<inv_tb>\\t%<w>0, <sizem1>, ");
988 else
989 {
990 char buf[64];
991 uint64_t val = ((uint64_t) 1)
992 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
993 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
994 output_asm_insn (buf, operands);
995 return "<bcond>\t%l1";
996 }
997 }
998 else
999 return "<tbz>\t%<w>0, <sizem1>, %l1";
1000 }
1001 [(set_attr "type" "branch")
1002 (set (attr "length")
1003 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
1004 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
1005 (const_int 4)
1006 (const_int 8)))
1007 (set (attr "far_branch")
1008 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
1009 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
1010 (const_int 0)
1011 (const_int 1)))]
1012 )
1013
1014 ;; -------------------------------------------------------------------
1015 ;; Subroutine calls and sibcalls
1016 ;; -------------------------------------------------------------------
1017
1018 (define_expand "call"
1019 [(parallel
1020 [(call (match_operand 0 "memory_operand")
1021 (match_operand 1 "general_operand"))
1022 (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1023 (clobber (reg:DI LR_REGNUM))])]
1024 ""
1025 "
1026 {
1027 aarch64_expand_call (NULL_RTX, operands[0], operands[2], false);
1028 DONE;
1029 }"
1030 )
1031
1032 (define_insn "*call_insn"
1033 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucr, Usf"))
1034 (match_operand 1 "" ""))
1035 (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1036 (clobber (reg:DI LR_REGNUM))]
1037 ""
1038 "@
1039 * return aarch64_indirect_call_asm (operands[0]);
1040 bl\\t%c0"
1041 [(set_attr "type" "call, call")])
1042
1043 (define_expand "call_value"
1044 [(parallel
1045 [(set (match_operand 0 "")
1046 (call (match_operand 1 "memory_operand")
1047 (match_operand 2 "general_operand")))
1048 (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1049 (clobber (reg:DI LR_REGNUM))])]
1050 ""
1051 "
1052 {
1053 aarch64_expand_call (operands[0], operands[1], operands[3], false);
1054 DONE;
1055 }"
1056 )
1057
1058 (define_insn "*call_value_insn"
1059 [(set (match_operand 0 "" "")
1060 (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "Ucr, Usf"))
1061 (match_operand 2 "" "")))
1062 (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1063 (clobber (reg:DI LR_REGNUM))]
1064 ""
1065 "@
1066 * return aarch64_indirect_call_asm (operands[1]);
1067 bl\\t%c1"
1068 [(set_attr "type" "call, call")]
1069 )
1070
1071 (define_expand "sibcall"
1072 [(parallel
1073 [(call (match_operand 0 "memory_operand")
1074 (match_operand 1 "general_operand"))
1075 (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1076 (return)])]
1077 ""
1078 {
1079 aarch64_expand_call (NULL_RTX, operands[0], operands[2], true);
1080 DONE;
1081 }
1082 )
1083
1084 (define_expand "sibcall_value"
1085 [(parallel
1086 [(set (match_operand 0 "")
1087 (call (match_operand 1 "memory_operand")
1088 (match_operand 2 "general_operand")))
1089 (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1090 (return)])]
1091 ""
1092 {
1093 aarch64_expand_call (operands[0], operands[1], operands[3], true);
1094 DONE;
1095 }
1096 )
1097
1098 (define_insn "*sibcall_insn"
1099 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
1100 (match_operand 1 ""))
1101 (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1102 (return)]
1103 "SIBLING_CALL_P (insn)"
1104 {
1105 if (which_alternative == 0)
1106 {
1107 output_asm_insn ("br\\t%0", operands);
1108 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1109 }
1110 return "b\\t%c0";
1111 }
1112 [(set_attr "type" "branch, branch")
1113 (set_attr "sls_length" "retbr,none")]
1114 )
1115
1116 (define_insn "*sibcall_value_insn"
1117 [(set (match_operand 0 "")
1118 (call (mem:DI
1119 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
1120 (match_operand 2 "")))
1121 (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1122 (return)]
1123 "SIBLING_CALL_P (insn)"
1124 {
1125 if (which_alternative == 0)
1126 {
1127 output_asm_insn ("br\\t%1", operands);
1128 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1129 }
1130 return "b\\t%c1";
1131 }
1132 [(set_attr "type" "branch, branch")
1133 (set_attr "sls_length" "retbr,none")]
1134 )
1135
1136 ;; Call subroutine returning any type.
1137
1138 (define_expand "untyped_call"
1139 [(parallel [(call (match_operand 0 "")
1140 (const_int 0))
1141 (match_operand 1 "")
1142 (match_operand 2 "")])]
1143 ""
1144 {
1145 int i;
1146
1147 /* Untyped calls always use the default ABI. It's only possible to use
1148 ABI variants if we know the type of the target function. */
1149 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
1150
1151 for (i = 0; i < XVECLEN (operands[2], 0); i++)
1152 {
1153 rtx set = XVECEXP (operands[2], 0, i);
1154 emit_move_insn (SET_DEST (set), SET_SRC (set));
1155 }
1156
1157 /* The optimizer does not know that the call sets the function value
1158 registers we stored in the result block. We avoid problems by
1159 claiming that all hard registers are used and clobbered at this
1160 point. */
1161 emit_insn (gen_blockage ());
1162 DONE;
1163 })
1164
1165 ;; -------------------------------------------------------------------
1166 ;; Moves
1167 ;; -------------------------------------------------------------------
1168
1169 (define_expand "mov<mode>"
1170 [(set (match_operand:SHORT 0 "nonimmediate_operand")
1171 (match_operand:SHORT 1 "general_operand"))]
1172 ""
1173 "
1174 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1175 operands[1] = force_reg (<MODE>mode, operands[1]);
1176
1177 if (GET_CODE (operands[1]) == CONST_POLY_INT)
1178 {
1179 aarch64_expand_mov_immediate (operands[0], operands[1]);
1180 DONE;
1181 }
1182 "
1183 )
1184
1185 (define_insn "*mov<mode>_aarch64"
1186 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
1187 (match_operand:SHORT 1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
1188 "(register_operand (operands[0], <MODE>mode)
1189 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
1190 {
1191 switch (which_alternative)
1192 {
1193 case 0:
1194 return "mov\t%w0, %w1";
1195 case 1:
1196 return "mov\t%w0, %1";
1197 case 2:
1198 return aarch64_output_scalar_simd_mov_immediate (operands[1],
1199 <MODE>mode);
1200 case 3:
1201 return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1202 case 4:
1203 return "ldr<size>\t%w0, %1";
1204 case 5:
1205 return "ldr\t%<size>0, %1";
1206 case 6:
1207 return "str<size>\t%w1, %0";
1208 case 7:
1209 return "str\t%<size>1, %0";
1210 case 8:
1211 return "umov\t%w0, %1.<v>[0]";
1212 case 9:
1213 return "dup\t%0.<Vallxd>, %w1";
1214 case 10:
1215 return "dup\t%<Vetype>0, %1.<v>[0]";
1216 default:
1217 gcc_unreachable ();
1218 }
1219 }
1220 ;; The "mov_imm" type for CNT is just a placeholder.
1221 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
1222 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1223 (set_attr "arch" "*,*,simd,sve,*,*,*,*,simd,simd,simd")]
1224 )
1225
1226 (define_expand "mov<mode>"
1227 [(set (match_operand:GPI 0 "nonimmediate_operand")
1228 (match_operand:GPI 1 "general_operand"))]
1229 ""
1230 "
1231 if (MEM_P (operands[0]) && !MEM_VOLATILE_P (operands[0])
1232 && CONST_INT_P (operands[1]) && <MODE>mode == DImode
1233 && aarch64_split_dimode_const_store (operands[0], operands[1]))
1234 DONE;
1235
1236 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1237 operands[1] = force_reg (<MODE>mode, operands[1]);
1238
1239 /* FIXME: RR we still need to fix up what we are doing with
1240 symbol_refs and other types of constants. */
1241 if (CONSTANT_P (operands[1])
1242 && !CONST_INT_P (operands[1]))
1243 {
1244 aarch64_expand_mov_immediate (operands[0], operands[1]);
1245 DONE;
1246 }
1247 "
1248 )
1249
1250 (define_insn_and_split "*movsi_aarch64"
1251 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1252 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1253 "(register_operand (operands[0], SImode)
1254 || aarch64_reg_or_zero (operands[1], SImode))"
1255 "@
1256 mov\\t%w0, %w1
1257 mov\\t%w0, %w1
1258 mov\\t%w0, %w1
1259 mov\\t%w0, %1
1260 #
1261 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1262 ldr\\t%w0, %1
1263 ldr\\t%s0, %1
1264 str\\t%w1, %0
1265 str\\t%s1, %0
1266 adr\\t%x0, %c1
1267 adrp\\t%x0, %A1
1268 fmov\\t%s0, %w1
1269 fmov\\t%w0, %s1
1270 fmov\\t%s0, %s1
1271 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
1272 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1273 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1274 [(const_int 0)]
1275 "{
1276 aarch64_expand_mov_immediate (operands[0], operands[1]);
1277 DONE;
1278 }"
1279 ;; The "mov_imm" type for CNT is just a placeholder.
1280 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1281 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1282 (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1283 )
1284
1285 (define_insn_and_split "*movdi_aarch64"
1286 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1287 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1288 "(register_operand (operands[0], DImode)
1289 || aarch64_reg_or_zero (operands[1], DImode))"
1290 "@
1291 mov\\t%x0, %x1
1292 mov\\t%0, %x1
1293 mov\\t%x0, %1
1294 mov\\t%x0, %1
1295 mov\\t%w0, %1
1296 #
1297 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1298 ldr\\t%x0, %1
1299 ldr\\t%d0, %1
1300 str\\t%x1, %0
1301 str\\t%d1, %0
1302 adr\\t%x0, %c1
1303 adrp\\t%x0, %A1
1304 fmov\\t%d0, %x1
1305 fmov\\t%x0, %d1
1306 fmov\\t%d0, %d1
1307 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
1308 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1309 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1310 [(const_int 0)]
1311 "{
1312 aarch64_expand_mov_immediate (operands[0], operands[1]);
1313 DONE;
1314 }"
1315 ;; The "mov_imm" type for CNTD is just a placeholder.
1316 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1317 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1318 neon_move")
1319 (set_attr "arch" "*,*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1320 )
1321
1322 (define_insn "insv_imm<mode>"
1323 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1324 (const_int 16)
1325 (match_operand:GPI 1 "const_int_operand" "n"))
1326 (match_operand:GPI 2 "const_int_operand" "n"))]
1327 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1328 && UINTVAL (operands[1]) % 16 == 0"
1329 "movk\\t%<w>0, %X2, lsl %1"
1330 [(set_attr "type" "mov_imm")]
1331 )
1332
1333 ;; Match MOVK as a normal AND and IOR operation.
1334 (define_insn "aarch64_movk<mode>"
1335 [(set (match_operand:GPI 0 "register_operand" "=r")
1336 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
1337 (match_operand:GPI 2 "const_int_operand"))
1338 (match_operand:GPI 3 "const_int_operand")))]
1339 "aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
1340 rtx_mode_t (operands[3], <MODE>mode)) >= 0"
1341 {
1342 int shift = aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
1343 rtx_mode_t (operands[3], <MODE>mode));
1344 operands[2] = gen_int_mode (UINTVAL (operands[3]) >> shift, SImode);
1345 operands[3] = gen_int_mode (shift, SImode);
1346 return "movk\\t%<w>0, #%X2, lsl %3";
1347 }
1348 [(set_attr "type" "mov_imm")]
1349 )
1350
1351 (define_expand "movti"
1352 [(set (match_operand:TI 0 "nonimmediate_operand")
1353 (match_operand:TI 1 "general_operand"))]
1354 ""
1355 "
1356 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1357 operands[1] = force_reg (TImode, operands[1]);
1358
1359 if (GET_CODE (operands[1]) == CONST_POLY_INT)
1360 {
1361 emit_move_insn (gen_lowpart (DImode, operands[0]),
1362 gen_lowpart (DImode, operands[1]));
1363 emit_move_insn (gen_highpart (DImode, operands[0]), const0_rtx);
1364 DONE;
1365 }
1366 "
1367 )
1368
1369 (define_insn "*movti_aarch64"
1370 [(set (match_operand:TI 0
1371 "nonimmediate_operand" "= r,w,w, r,w,r,m,m,w,m")
1372 (match_operand:TI 1
1373 "aarch64_movti_operand" " rUti,Z,r, w,w,m,r,Z,m,w"))]
1374 "(register_operand (operands[0], TImode)
1375 || aarch64_reg_or_zero (operands[1], TImode))"
1376 "@
1377 #
1378 movi\\t%0.2d, #0
1379 #
1380 #
1381 mov\\t%0.16b, %1.16b
1382 ldp\\t%0, %H0, %1
1383 stp\\t%1, %H1, %0
1384 stp\\txzr, xzr, %0
1385 ldr\\t%q0, %1
1386 str\\t%q1, %0"
1387 [(set_attr "type" "multiple,neon_move,f_mcr,f_mrc,neon_logic_q, \
1388 load_16,store_16,store_16,\
1389 load_16,store_16")
1390 (set_attr "length" "8,4,8,8,4,4,4,4,4,4")
1391 (set_attr "arch" "*,simd,*,*,simd,*,*,*,fp,fp")]
1392 )
1393
1394 ;; Split a TImode register-register or register-immediate move into
1395 ;; its component DImode pieces, taking care to handle overlapping
1396 ;; source and dest registers.
1397 (define_split
1398 [(set (match_operand:TI 0 "register_operand" "")
1399 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1400 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1401 [(const_int 0)]
1402 {
1403 aarch64_split_128bit_move (operands[0], operands[1]);
1404 DONE;
1405 })
1406
1407 (define_expand "mov<mode>"
1408 [(set (match_operand:GPF_TF_F16_MOV 0 "nonimmediate_operand")
1409 (match_operand:GPF_TF_F16_MOV 1 "general_operand"))]
1410 ""
1411 {
1412 if (!TARGET_FLOAT)
1413 {
1414 aarch64_err_no_fpadvsimd (<MODE>mode);
1415 machine_mode intmode
1416 = int_mode_for_size (GET_MODE_BITSIZE (<MODE>mode), 0).require ();
1417 emit_move_insn (gen_lowpart (intmode, operands[0]),
1418 gen_lowpart (intmode, operands[1]));
1419 DONE;
1420 }
1421
1422 if (GET_CODE (operands[0]) == MEM
1423 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1424 && aarch64_float_const_zero_rtx_p (operands[1])))
1425 operands[1] = force_reg (<MODE>mode, operands[1]);
1426 }
1427 )
1428
1429 (define_insn "*mov<mode>_aarch64"
1430 [(set (match_operand:HFBF 0 "nonimmediate_operand" "=w,w , w,?r,w,w ,w ,w,m,r,m ,r")
1431 (match_operand:HFBF 1 "general_operand" "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1432 "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
1433 || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
1434 "@
1435 movi\\t%0.4h, #0
1436 fmov\\t%h0, %w1
1437 dup\\t%w0.4h, %w1
1438 umov\\t%w0, %1.h[0]
1439 mov\\t%0.h[0], %1.h[0]
1440 fmov\\t%h0, %1
1441 * return aarch64_output_scalar_simd_mov_immediate (operands[1], HImode);
1442 ldr\\t%h0, %1
1443 str\\t%h1, %0
1444 ldrh\\t%w0, %1
1445 strh\\t%w1, %0
1446 mov\\t%w0, %w1"
1447 [(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
1448 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1449 (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
1450 )
1451
1452 (define_insn "*movsf_aarch64"
1453 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1454 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1455 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1456 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1457 "@
1458 movi\\t%0.2s, #0
1459 fmov\\t%s0, %w1
1460 fmov\\t%w0, %s1
1461 fmov\\t%s0, %s1
1462 fmov\\t%s0, %1
1463 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1464 ldr\\t%s0, %1
1465 str\\t%s1, %0
1466 ldr\\t%w0, %1
1467 str\\t%w1, %0
1468 mov\\t%w0, %w1
1469 mov\\t%w0, %1"
1470 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1471 f_loads,f_stores,load_4,store_4,mov_reg,\
1472 fconsts")
1473 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1474 )
1475
1476 (define_insn "*movdf_aarch64"
1477 [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1478 (match_operand:DF 1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1479 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1480 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1481 "@
1482 movi\\t%d0, #0
1483 fmov\\t%d0, %x1
1484 fmov\\t%x0, %d1
1485 fmov\\t%d0, %d1
1486 fmov\\t%d0, %1
1487 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
1488 ldr\\t%d0, %1
1489 str\\t%d1, %0
1490 ldr\\t%x0, %1
1491 str\\t%x1, %0
1492 mov\\t%x0, %x1
1493 mov\\t%x0, %1"
1494 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1495 f_loadd,f_stored,load_8,store_8,mov_reg,\
1496 fconstd")
1497 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1498 )
1499
1500 (define_split
1501 [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
1502 (match_operand:GPF_HF 1 "general_operand"))]
1503 "can_create_pseudo_p ()
1504 && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
1505 && !aarch64_float_const_representable_p (operands[1])
1506 && aarch64_float_const_rtx_p (operands[1])"
1507 [(const_int 0)]
1508 {
1509 unsigned HOST_WIDE_INT ival;
1510 if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
1511 FAIL;
1512
1513 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1514 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1515 emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
1516 DONE;
1517 }
1518 )
1519
1520 (define_insn "*movtf_aarch64"
1521 [(set (match_operand:TF 0
1522 "nonimmediate_operand" "=w,?r ,w ,?r,w,?w,w,m,?r,m ,m")
1523 (match_operand:TF 1
1524 "general_operand" " w,?rY,?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1525 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1526 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1527 "@
1528 mov\\t%0.16b, %1.16b
1529 #
1530 #
1531 #
1532 movi\\t%0.2d, #0
1533 fmov\\t%s0, wzr
1534 ldr\\t%q0, %1
1535 str\\t%q1, %0
1536 ldp\\t%0, %H0, %1
1537 stp\\t%1, %H1, %0
1538 stp\\txzr, xzr, %0"
1539 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1540 f_loadd,f_stored,load_16,store_16,store_16")
1541 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1542 (set_attr "arch" "simd,*,*,*,simd,*,*,*,*,*,*")]
1543 )
1544
1545 (define_split
1546 [(set (match_operand:TF 0 "register_operand" "")
1547 (match_operand:TF 1 "nonmemory_operand" ""))]
1548 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1549 [(const_int 0)]
1550 {
1551 aarch64_split_128bit_move (operands[0], operands[1]);
1552 DONE;
1553 }
1554 )
1555
1556 ;; 0 is dst
1557 ;; 1 is src
1558 ;; 2 is size of copy in bytes
1559 ;; 3 is alignment
1560
1561 (define_expand "cpymemdi"
1562 [(match_operand:BLK 0 "memory_operand")
1563 (match_operand:BLK 1 "memory_operand")
1564 (match_operand:DI 2 "immediate_operand")
1565 (match_operand:DI 3 "immediate_operand")]
1566 "!STRICT_ALIGNMENT"
1567 {
1568 if (aarch64_expand_cpymem (operands))
1569 DONE;
1570 FAIL;
1571 }
1572 )
1573
1574 ;; 0 is dst
1575 ;; 1 is val
1576 ;; 2 is size of copy in bytes
1577 ;; 3 is alignment
1578
1579 (define_expand "setmemdi"
1580 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
1581 (match_operand:QI 2 "nonmemory_operand")) ;; Value
1582 (use (match_operand:DI 1 "immediate_operand")) ;; Length
1583 (match_operand 3 "immediate_operand")] ;; Align
1584 "TARGET_SIMD"
1585 {
1586 if (aarch64_expand_setmem (operands))
1587 DONE;
1588
1589 FAIL;
1590 })
1591
1592 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1593 ;; fairly lax checking on the second memory operation.
1594 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1595 [(set (match_operand:SX 0 "register_operand" "=r,w")
1596 (match_operand:SX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1597 (set (match_operand:SX2 2 "register_operand" "=r,w")
1598 (match_operand:SX2 3 "memory_operand" "m,m"))]
1599 "rtx_equal_p (XEXP (operands[3], 0),
1600 plus_constant (Pmode,
1601 XEXP (operands[1], 0),
1602 GET_MODE_SIZE (<SX:MODE>mode)))"
1603 "@
1604 ldp\\t%w0, %w2, %z1
1605 ldp\\t%s0, %s2, %z1"
1606 [(set_attr "type" "load_8,neon_load1_2reg")
1607 (set_attr "arch" "*,fp")]
1608 )
1609
1610 ;; Storing different modes that can still be merged
1611 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1612 [(set (match_operand:DX 0 "register_operand" "=r,w")
1613 (match_operand:DX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1614 (set (match_operand:DX2 2 "register_operand" "=r,w")
1615 (match_operand:DX2 3 "memory_operand" "m,m"))]
1616 "rtx_equal_p (XEXP (operands[3], 0),
1617 plus_constant (Pmode,
1618 XEXP (operands[1], 0),
1619 GET_MODE_SIZE (<DX:MODE>mode)))"
1620 "@
1621 ldp\\t%x0, %x2, %z1
1622 ldp\\t%d0, %d2, %z1"
1623 [(set_attr "type" "load_16,neon_load1_2reg")
1624 (set_attr "arch" "*,fp")]
1625 )
1626
1627 (define_insn "load_pair_dw_tftf"
1628 [(set (match_operand:TF 0 "register_operand" "=w")
1629 (match_operand:TF 1 "aarch64_mem_pair_operand" "Ump"))
1630 (set (match_operand:TF 2 "register_operand" "=w")
1631 (match_operand:TF 3 "memory_operand" "m"))]
1632 "TARGET_SIMD
1633 && rtx_equal_p (XEXP (operands[3], 0),
1634 plus_constant (Pmode,
1635 XEXP (operands[1], 0),
1636 GET_MODE_SIZE (TFmode)))"
1637 "ldp\\t%q0, %q2, %z1"
1638 [(set_attr "type" "neon_ldp_q")
1639 (set_attr "fp" "yes")]
1640 )
1641
1642 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1643 ;; fairly lax checking on the second memory operation.
1644 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1645 [(set (match_operand:SX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1646 (match_operand:SX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1647 (set (match_operand:SX2 2 "memory_operand" "=m,m")
1648 (match_operand:SX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1649 "rtx_equal_p (XEXP (operands[2], 0),
1650 plus_constant (Pmode,
1651 XEXP (operands[0], 0),
1652 GET_MODE_SIZE (<SX:MODE>mode)))"
1653 "@
1654 stp\\t%w1, %w3, %z0
1655 stp\\t%s1, %s3, %z0"
1656 [(set_attr "type" "store_8,neon_store1_2reg")
1657 (set_attr "arch" "*,fp")]
1658 )
1659
1660 ;; Storing different modes that can still be merged
1661 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1662 [(set (match_operand:DX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1663 (match_operand:DX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1664 (set (match_operand:DX2 2 "memory_operand" "=m,m")
1665 (match_operand:DX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1666 "rtx_equal_p (XEXP (operands[2], 0),
1667 plus_constant (Pmode,
1668 XEXP (operands[0], 0),
1669 GET_MODE_SIZE (<DX:MODE>mode)))"
1670 "@
1671 stp\\t%x1, %x3, %z0
1672 stp\\t%d1, %d3, %z0"
1673 [(set_attr "type" "store_16,neon_store1_2reg")
1674 (set_attr "arch" "*,fp")]
1675 )
1676
1677 (define_insn "store_pair_dw_tftf"
1678 [(set (match_operand:TF 0 "aarch64_mem_pair_operand" "=Ump")
1679 (match_operand:TF 1 "register_operand" "w"))
1680 (set (match_operand:TF 2 "memory_operand" "=m")
1681 (match_operand:TF 3 "register_operand" "w"))]
1682 "TARGET_SIMD &&
1683 rtx_equal_p (XEXP (operands[2], 0),
1684 plus_constant (Pmode,
1685 XEXP (operands[0], 0),
1686 GET_MODE_SIZE (TFmode)))"
1687 "stp\\t%q1, %q3, %z0"
1688 [(set_attr "type" "neon_stp_q")
1689 (set_attr "fp" "yes")]
1690 )
1691
1692 ;; Load pair with post-index writeback. This is primarily used in function
1693 ;; epilogues.
1694 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1695 [(parallel
1696 [(set (match_operand:P 0 "register_operand" "=k")
1697 (plus:P (match_operand:P 1 "register_operand" "0")
1698 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1699 (set (match_operand:GPI 2 "register_operand" "=r")
1700 (mem:GPI (match_dup 1)))
1701 (set (match_operand:GPI 3 "register_operand" "=r")
1702 (mem:GPI (plus:P (match_dup 1)
1703 (match_operand:P 5 "const_int_operand" "n"))))])]
1704 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1705 "ldp\\t%<GPI:w>2, %<GPI:w>3, [%1], %4"
1706 [(set_attr "type" "load_<GPI:ldpstp_sz>")]
1707 )
1708
1709 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1710 [(parallel
1711 [(set (match_operand:P 0 "register_operand" "=k")
1712 (plus:P (match_operand:P 1 "register_operand" "0")
1713 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1714 (set (match_operand:GPF 2 "register_operand" "=w")
1715 (mem:GPF (match_dup 1)))
1716 (set (match_operand:GPF 3 "register_operand" "=w")
1717 (mem:GPF (plus:P (match_dup 1)
1718 (match_operand:P 5 "const_int_operand" "n"))))])]
1719 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1720 "ldp\\t%<GPF:w>2, %<GPF:w>3, [%1], %4"
1721 [(set_attr "type" "neon_load1_2reg")]
1722 )
1723
1724 (define_insn "loadwb_pair<TX:mode>_<P:mode>"
1725 [(parallel
1726 [(set (match_operand:P 0 "register_operand" "=k")
1727 (plus:P (match_operand:P 1 "register_operand" "0")
1728 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1729 (set (match_operand:TX 2 "register_operand" "=w")
1730 (mem:TX (match_dup 1)))
1731 (set (match_operand:TX 3 "register_operand" "=w")
1732 (mem:TX (plus:P (match_dup 1)
1733 (match_operand:P 5 "const_int_operand" "n"))))])]
1734 "TARGET_SIMD && INTVAL (operands[5]) == GET_MODE_SIZE (<TX:MODE>mode)"
1735 "ldp\\t%q2, %q3, [%1], %4"
1736 [(set_attr "type" "neon_ldp_q")]
1737 )
1738
1739 ;; Store pair with pre-index writeback. This is primarily used in function
1740 ;; prologues.
1741 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1742 [(parallel
1743 [(set (match_operand:P 0 "register_operand" "=&k")
1744 (plus:P (match_operand:P 1 "register_operand" "0")
1745 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1746 (set (mem:GPI (plus:P (match_dup 0)
1747 (match_dup 4)))
1748 (match_operand:GPI 2 "register_operand" "r"))
1749 (set (mem:GPI (plus:P (match_dup 0)
1750 (match_operand:P 5 "const_int_operand" "n")))
1751 (match_operand:GPI 3 "register_operand" "r"))])]
1752 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1753 "stp\\t%<GPI:w>2, %<GPI:w>3, [%0, %4]!"
1754 [(set_attr "type" "store_<GPI:ldpstp_sz>")]
1755 )
1756
1757 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1758 [(parallel
1759 [(set (match_operand:P 0 "register_operand" "=&k")
1760 (plus:P (match_operand:P 1 "register_operand" "0")
1761 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1762 (set (mem:GPF (plus:P (match_dup 0)
1763 (match_dup 4)))
1764 (match_operand:GPF 2 "register_operand" "w"))
1765 (set (mem:GPF (plus:P (match_dup 0)
1766 (match_operand:P 5 "const_int_operand" "n")))
1767 (match_operand:GPF 3 "register_operand" "w"))])]
1768 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1769 "stp\\t%<GPF:w>2, %<GPF:w>3, [%0, %4]!"
1770 [(set_attr "type" "neon_store1_2reg<q>")]
1771 )
1772
1773 (define_insn "storewb_pair<TX:mode>_<P:mode>"
1774 [(parallel
1775 [(set (match_operand:P 0 "register_operand" "=&k")
1776 (plus:P (match_operand:P 1 "register_operand" "0")
1777 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1778 (set (mem:TX (plus:P (match_dup 0)
1779 (match_dup 4)))
1780 (match_operand:TX 2 "register_operand" "w"))
1781 (set (mem:TX (plus:P (match_dup 0)
1782 (match_operand:P 5 "const_int_operand" "n")))
1783 (match_operand:TX 3 "register_operand" "w"))])]
1784 "TARGET_SIMD
1785 && INTVAL (operands[5])
1786 == INTVAL (operands[4]) + GET_MODE_SIZE (<TX:MODE>mode)"
1787 "stp\\t%q2, %q3, [%0, %4]!"
1788 [(set_attr "type" "neon_stp_q")]
1789 )
1790
1791 ;; -------------------------------------------------------------------
1792 ;; Sign/Zero extension
1793 ;; -------------------------------------------------------------------
1794
1795 (define_expand "<optab>sidi2"
1796 [(set (match_operand:DI 0 "register_operand")
1797 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1798 ""
1799 )
1800
1801 (define_insn "*extendsidi2_aarch64"
1802 [(set (match_operand:DI 0 "register_operand" "=r,r")
1803 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1804 ""
1805 "@
1806 sxtw\t%0, %w1
1807 ldrsw\t%0, %1"
1808 [(set_attr "type" "extend,load_4")]
1809 )
1810
1811 (define_insn "*load_pair_extendsidi2_aarch64"
1812 [(set (match_operand:DI 0 "register_operand" "=r")
1813 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1814 (set (match_operand:DI 2 "register_operand" "=r")
1815 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1816 "rtx_equal_p (XEXP (operands[3], 0),
1817 plus_constant (Pmode,
1818 XEXP (operands[1], 0),
1819 GET_MODE_SIZE (SImode)))"
1820 "ldpsw\\t%0, %2, %z1"
1821 [(set_attr "type" "load_8")]
1822 )
1823
1824 (define_insn "*zero_extendsidi2_aarch64"
1825 [(set (match_operand:DI 0 "register_operand" "=r,r,w,w,r,w")
1826 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,r,m,w,w")))]
1827 ""
1828 "@
1829 uxtw\t%0, %w1
1830 ldr\t%w0, %1
1831 fmov\t%s0, %w1
1832 ldr\t%s0, %1
1833 fmov\t%w0, %s1
1834 fmov\t%s0, %s1"
1835 [(set_attr "type" "mov_reg,load_4,f_mcr,f_loads,f_mrc,fmov")
1836 (set_attr "arch" "*,*,fp,fp,fp,fp")]
1837 )
1838
1839 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1840 [(set (match_operand:DI 0 "register_operand" "=r,w")
1841 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump")))
1842 (set (match_operand:DI 2 "register_operand" "=r,w")
1843 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m,m")))]
1844 "rtx_equal_p (XEXP (operands[3], 0),
1845 plus_constant (Pmode,
1846 XEXP (operands[1], 0),
1847 GET_MODE_SIZE (SImode)))"
1848 "@
1849 ldp\t%w0, %w2, %z1
1850 ldp\t%s0, %s2, %z1"
1851 [(set_attr "type" "load_8,neon_load1_2reg")
1852 (set_attr "arch" "*,fp")]
1853 )
1854
1855 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1856 [(set (match_operand:GPI 0 "register_operand")
1857 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1858 ""
1859 )
1860
1861 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1862 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1863 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1864 ""
1865 "@
1866 sxt<SHORT:size>\t%<GPI:w>0, %w1
1867 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1868 [(set_attr "type" "extend,load_4")]
1869 )
1870
1871 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1872 [(set (match_operand:GPI 0 "register_operand" "=r,r,w")
1873 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1874 ""
1875 "@
1876 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1877 ldr<SHORT:size>\t%w0, %1
1878 ldr\t%<SHORT:size>0, %1"
1879 [(set_attr "type" "logic_imm,load_4,f_loads")
1880 (set_attr "arch" "*,*,fp")]
1881 )
1882
1883 (define_expand "<optab>qihi2"
1884 [(set (match_operand:HI 0 "register_operand")
1885 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1886 ""
1887 )
1888
1889 (define_insn "*extendqihi2_aarch64"
1890 [(set (match_operand:HI 0 "register_operand" "=r,r")
1891 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1892 ""
1893 "@
1894 sxtb\t%w0, %w1
1895 ldrsb\t%w0, %1"
1896 [(set_attr "type" "extend,load_4")]
1897 )
1898
1899 (define_insn "*zero_extendqihi2_aarch64"
1900 [(set (match_operand:HI 0 "register_operand" "=r,r")
1901 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1902 ""
1903 "@
1904 and\t%w0, %w1, 255
1905 ldrb\t%w0, %1"
1906 [(set_attr "type" "logic_imm,load_4")]
1907 )
1908
1909 ;; -------------------------------------------------------------------
1910 ;; Simple arithmetic
1911 ;; -------------------------------------------------------------------
1912
1913 (define_expand "add<mode>3"
1914 [(set
1915 (match_operand:GPI 0 "register_operand")
1916 (plus:GPI (match_operand:GPI 1 "register_operand")
1917 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand")))]
1918 ""
1919 {
1920 /* If operands[1] is a subreg extract the inner RTX. */
1921 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1922
1923 /* If the constant is too large for a single instruction and isn't frame
1924 based, split off the immediate so it is available for CSE. */
1925 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1926 && !(TARGET_SVE && aarch64_sve_plus_immediate (operands[2], <MODE>mode))
1927 && can_create_pseudo_p ()
1928 && (!REG_P (op1)
1929 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1930 operands[2] = force_reg (<MODE>mode, operands[2]);
1931 /* Expand polynomial additions now if the destination is the stack
1932 pointer, since we don't want to use that as a temporary. */
1933 else if (operands[0] == stack_pointer_rtx
1934 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode))
1935 {
1936 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
1937 operands[2], NULL_RTX, NULL_RTX);
1938 DONE;
1939 }
1940 })
1941
1942 (define_insn "*add<mode>3_aarch64"
1943 [(set
1944 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r,r,rk")
1945 (plus:GPI
1946 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk,0,rk")
1947 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uai,Uav")))]
1948 ""
1949 "@
1950 add\\t%<w>0, %<w>1, %2
1951 add\\t%<w>0, %<w>1, %<w>2
1952 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1953 sub\\t%<w>0, %<w>1, #%n2
1954 #
1955 * return aarch64_output_sve_scalar_inc_dec (operands[2]);
1956 * return aarch64_output_sve_addvl_addpl (operands[2]);"
1957 ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
1958 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm,alu_imm")
1959 (set_attr "arch" "*,*,simd,*,*,sve,sve")]
1960 )
1961
1962 ;; zero_extend version of above
1963 (define_insn "*addsi3_aarch64_uxtw"
1964 [(set
1965 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1966 (zero_extend:DI
1967 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1968 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1969 ""
1970 "@
1971 add\\t%w0, %w1, %2
1972 add\\t%w0, %w1, %w2
1973 sub\\t%w0, %w1, #%n2
1974 #"
1975 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1976 )
1977
1978 ;; If there's a free register, and we can load the constant with a
1979 ;; single instruction, do so. This has a chance to improve scheduling.
1980 (define_peephole2
1981 [(match_scratch:GPI 3 "r")
1982 (set (match_operand:GPI 0 "register_operand")
1983 (plus:GPI
1984 (match_operand:GPI 1 "register_operand")
1985 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1986 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1987 [(set (match_dup 3) (match_dup 2))
1988 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1989 )
1990
1991 (define_peephole2
1992 [(match_scratch:SI 3 "r")
1993 (set (match_operand:DI 0 "register_operand")
1994 (zero_extend:DI
1995 (plus:SI
1996 (match_operand:SI 1 "register_operand")
1997 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1998 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1999 [(set (match_dup 3) (match_dup 2))
2000 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
2001 )
2002
2003 ;; After peephole2 has had a chance to run, split any remaining long
2004 ;; additions into two add immediates.
2005 (define_split
2006 [(set (match_operand:GPI 0 "register_operand")
2007 (plus:GPI
2008 (match_operand:GPI 1 "register_operand")
2009 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
2010 "epilogue_completed"
2011 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
2012 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
2013 {
2014 HOST_WIDE_INT i = INTVAL (operands[2]);
2015 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
2016 operands[3] = GEN_INT (i - s);
2017 operands[4] = GEN_INT (s);
2018 }
2019 )
2020
2021 ;; Match addition of polynomial offsets that require one temporary, for which
2022 ;; we can use the early-clobbered destination register. This is a separate
2023 ;; pattern so that the early clobber doesn't affect register allocation
2024 ;; for other forms of addition. However, we still need to provide an
2025 ;; all-register alternative, in case the offset goes out of range after
2026 ;; elimination. For completeness we might as well provide all GPR-based
2027 ;; alternatives from the main pattern.
2028 ;;
2029 ;; We don't have a pattern for additions requiring two temporaries since at
2030 ;; present LRA doesn't allow new scratches to be added during elimination.
2031 ;; Such offsets should be rare anyway.
2032 ;;
2033 ;; ??? But if we added LRA support for new scratches, much of the ugliness
2034 ;; here would go away. We could just handle all polynomial constants in
2035 ;; this pattern.
2036 (define_insn_and_split "*add<mode>3_poly_1"
2037 [(set
2038 (match_operand:GPI 0 "register_operand" "=r,r,r,r,r,r,&r")
2039 (plus:GPI
2040 (match_operand:GPI 1 "register_operand" "%rk,rk,rk,rk,rk,0,rk")
2041 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uai,Uat")))]
2042 "TARGET_SVE && operands[0] != stack_pointer_rtx"
2043 "@
2044 add\\t%<w>0, %<w>1, %2
2045 add\\t%<w>0, %<w>1, %<w>2
2046 sub\\t%<w>0, %<w>1, #%n2
2047 #
2048 * return aarch64_output_sve_scalar_inc_dec (operands[2]);
2049 * return aarch64_output_sve_addvl_addpl (operands[2]);
2050 #"
2051 "&& epilogue_completed
2052 && !reg_overlap_mentioned_p (operands[0], operands[1])
2053 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode)"
2054 [(const_int 0)]
2055 {
2056 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
2057 operands[2], operands[0], NULL_RTX);
2058 DONE;
2059 }
2060 ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
2061 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,alu_imm,multiple")]
2062 )
2063
2064 (define_split
2065 [(set (match_operand:DI 0 "register_operand")
2066 (zero_extend:DI
2067 (plus:SI
2068 (match_operand:SI 1 "register_operand")
2069 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
2070 "epilogue_completed"
2071 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
2072 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
2073 {
2074 HOST_WIDE_INT i = INTVAL (operands[2]);
2075 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
2076 operands[3] = GEN_INT (i - s);
2077 operands[4] = GEN_INT (s);
2078 operands[5] = gen_lowpart (SImode, operands[0]);
2079 }
2080 )
2081
2082 (define_expand "addv<mode>4"
2083 [(match_operand:GPI 0 "register_operand")
2084 (match_operand:GPI 1 "register_operand")
2085 (match_operand:GPI 2 "aarch64_plus_operand")
2086 (label_ref (match_operand 3 "" ""))]
2087 ""
2088 {
2089 if (CONST_INT_P (operands[2]))
2090 emit_insn (gen_add<mode>3_compareV_imm (operands[0], operands[1],
2091 operands[2]));
2092 else
2093 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
2094 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2095
2096 DONE;
2097 })
2098
2099 (define_expand "uaddv<mode>4"
2100 [(match_operand:GPI 0 "register_operand")
2101 (match_operand:GPI 1 "register_operand")
2102 (match_operand:GPI 2 "register_operand")
2103 (label_ref (match_operand 3 "" ""))]
2104 ""
2105 {
2106 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
2107 aarch64_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
2108
2109 DONE;
2110 })
2111
2112 (define_expand "addti3"
2113 [(set (match_operand:TI 0 "register_operand")
2114 (plus:TI (match_operand:TI 1 "register_operand")
2115 (match_operand:TI 2 "aarch64_reg_or_imm")))]
2116 ""
2117 {
2118 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2119
2120 aarch64_addti_scratch_regs (operands[1], operands[2],
2121 &low_dest, &op1_low, &op2_low,
2122 &high_dest, &op1_high, &op2_high);
2123
2124 if (op2_low == const0_rtx)
2125 {
2126 low_dest = op1_low;
2127 if (!aarch64_pluslong_operand (op2_high, DImode))
2128 op2_high = force_reg (DImode, op2_high);
2129 emit_insn (gen_adddi3 (high_dest, op1_high, op2_high));
2130 }
2131 else
2132 {
2133 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2134 force_reg (DImode, op2_low)));
2135 emit_insn (gen_adddi3_carryin (high_dest, op1_high,
2136 force_reg (DImode, op2_high)));
2137 }
2138
2139 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2140 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2141
2142 DONE;
2143 })
2144
2145 (define_expand "addvti4"
2146 [(match_operand:TI 0 "register_operand")
2147 (match_operand:TI 1 "register_operand")
2148 (match_operand:TI 2 "aarch64_reg_or_imm")
2149 (label_ref (match_operand 3 "" ""))]
2150 ""
2151 {
2152 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2153
2154 aarch64_addti_scratch_regs (operands[1], operands[2],
2155 &low_dest, &op1_low, &op2_low,
2156 &high_dest, &op1_high, &op2_high);
2157
2158 if (op2_low == const0_rtx)
2159 {
2160 low_dest = op1_low;
2161 emit_insn (gen_adddi3_compareV (high_dest, op1_high,
2162 force_reg (DImode, op2_high)));
2163 }
2164 else
2165 {
2166 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2167 force_reg (DImode, op2_low)));
2168 emit_insn (gen_adddi3_carryinV (high_dest, op1_high,
2169 force_reg (DImode, op2_high)));
2170 }
2171
2172 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2173 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2174
2175 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2176 DONE;
2177 })
2178
2179 (define_expand "uaddvti4"
2180 [(match_operand:TI 0 "register_operand")
2181 (match_operand:TI 1 "register_operand")
2182 (match_operand:TI 2 "aarch64_reg_or_imm")
2183 (label_ref (match_operand 3 "" ""))]
2184 ""
2185 {
2186 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2187
2188 aarch64_addti_scratch_regs (operands[1], operands[2],
2189 &low_dest, &op1_low, &op2_low,
2190 &high_dest, &op1_high, &op2_high);
2191
2192 if (op2_low == const0_rtx)
2193 {
2194 low_dest = op1_low;
2195 emit_insn (gen_adddi3_compareC (high_dest, op1_high,
2196 force_reg (DImode, op2_high)));
2197 }
2198 else
2199 {
2200 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2201 force_reg (DImode, op2_low)));
2202 emit_insn (gen_adddi3_carryinC (high_dest, op1_high,
2203 force_reg (DImode, op2_high)));
2204 }
2205
2206 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2207 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2208
2209 aarch64_gen_unlikely_cbranch (GEU, CC_ADCmode, operands[3]);
2210 DONE;
2211 })
2212
2213 (define_insn "add<mode>3_compare0"
2214 [(set (reg:CC_NZ CC_REGNUM)
2215 (compare:CC_NZ
2216 (plus:GPI (match_operand:GPI 1 "register_operand" "%rk,rk,rk")
2217 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
2218 (const_int 0)))
2219 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
2220 (plus:GPI (match_dup 1) (match_dup 2)))]
2221 ""
2222 "@
2223 adds\\t%<w>0, %<w>1, %<w>2
2224 adds\\t%<w>0, %<w>1, %2
2225 subs\\t%<w>0, %<w>1, #%n2"
2226 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2227 )
2228
2229 ;; zero_extend version of above
2230 (define_insn "*addsi3_compare0_uxtw"
2231 [(set (reg:CC_NZ CC_REGNUM)
2232 (compare:CC_NZ
2233 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk")
2234 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
2235 (const_int 0)))
2236 (set (match_operand:DI 0 "register_operand" "=r,r,r")
2237 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
2238 ""
2239 "@
2240 adds\\t%w0, %w1, %w2
2241 adds\\t%w0, %w1, %2
2242 subs\\t%w0, %w1, #%n2"
2243 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2244 )
2245
2246 (define_insn "*add<mode>3_compareC_cconly"
2247 [(set (reg:CC_C CC_REGNUM)
2248 (compare:CC_C
2249 (plus:GPI
2250 (match_operand:GPI 0 "register_operand" "r,r,r")
2251 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2252 (match_dup 0)))]
2253 ""
2254 "@
2255 cmn\\t%<w>0, %<w>1
2256 cmn\\t%<w>0, %1
2257 cmp\\t%<w>0, #%n1"
2258 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2259 )
2260
2261 (define_insn "add<mode>3_compareC"
2262 [(set (reg:CC_C CC_REGNUM)
2263 (compare:CC_C
2264 (plus:GPI
2265 (match_operand:GPI 1 "register_operand" "rk,rk,rk")
2266 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
2267 (match_dup 1)))
2268 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
2269 (plus:GPI (match_dup 1) (match_dup 2)))]
2270 ""
2271 "@
2272 adds\\t%<w>0, %<w>1, %<w>2
2273 adds\\t%<w>0, %<w>1, %2
2274 subs\\t%<w>0, %<w>1, #%n2"
2275 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2276 )
2277
2278 (define_insn "*add<mode>3_compareV_cconly_imm"
2279 [(set (reg:CC_V CC_REGNUM)
2280 (compare:CC_V
2281 (plus:<DWI>
2282 (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
2283 (match_operand:<DWI> 1 "const_scalar_int_operand" ""))
2284 (sign_extend:<DWI>
2285 (plus:GPI
2286 (match_dup 0)
2287 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))]
2288 "INTVAL (operands[1]) == INTVAL (operands[2])"
2289 "@
2290 cmn\\t%<w>0, %<w>1
2291 cmp\\t%<w>0, #%n1"
2292 [(set_attr "type" "alus_imm")]
2293 )
2294
2295 (define_insn "*add<mode>3_compareV_cconly"
2296 [(set (reg:CC_V CC_REGNUM)
2297 (compare:CC_V
2298 (plus:<DWI>
2299 (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
2300 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2301 (sign_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
2302 ""
2303 "cmn\\t%<w>0, %<w>1"
2304 [(set_attr "type" "alus_sreg")]
2305 )
2306
2307 (define_insn "add<mode>3_compareV_imm"
2308 [(set (reg:CC_V CC_REGNUM)
2309 (compare:CC_V
2310 (plus:<DWI>
2311 (sign_extend:<DWI>
2312 (match_operand:GPI 1 "register_operand" "rk,rk"))
2313 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J"))
2314 (sign_extend:<DWI>
2315 (plus:GPI (match_dup 1) (match_dup 2)))))
2316 (set (match_operand:GPI 0 "register_operand" "=r,r")
2317 (plus:GPI (match_dup 1) (match_dup 2)))]
2318 ""
2319 "@
2320 adds\\t%<w>0, %<w>1, %<w>2
2321 subs\\t%<w>0, %<w>1, #%n2"
2322 [(set_attr "type" "alus_imm,alus_imm")]
2323 )
2324
2325 (define_insn "add<mode>3_compareV"
2326 [(set (reg:CC_V CC_REGNUM)
2327 (compare:CC_V
2328 (plus:<DWI>
2329 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "rk"))
2330 (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2331 (sign_extend:<DWI> (plus:GPI (match_dup 1) (match_dup 2)))))
2332 (set (match_operand:GPI 0 "register_operand" "=r")
2333 (plus:GPI (match_dup 1) (match_dup 2)))]
2334 ""
2335 "adds\\t%<w>0, %<w>1, %<w>2"
2336 [(set_attr "type" "alus_sreg")]
2337 )
2338
2339 (define_insn "*adds_shift_imm_<mode>"
2340 [(set (reg:CC_NZ CC_REGNUM)
2341 (compare:CC_NZ
2342 (plus:GPI (ASHIFT:GPI
2343 (match_operand:GPI 1 "register_operand" "r")
2344 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2345 (match_operand:GPI 3 "register_operand" "r"))
2346 (const_int 0)))
2347 (set (match_operand:GPI 0 "register_operand" "=r")
2348 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
2349 (match_dup 3)))]
2350 ""
2351 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2352 [(set_attr "type" "alus_shift_imm")]
2353 )
2354
2355 (define_insn "*subs_shift_imm_<mode>"
2356 [(set (reg:CC_NZ CC_REGNUM)
2357 (compare:CC_NZ
2358 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2359 (ASHIFT:GPI
2360 (match_operand:GPI 2 "register_operand" "r")
2361 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
2362 (const_int 0)))
2363 (set (match_operand:GPI 0 "register_operand" "=r")
2364 (minus:GPI (match_dup 1)
2365 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
2366 ""
2367 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
2368 [(set_attr "type" "alus_shift_imm")]
2369 )
2370
2371 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
2372 [(set (reg:CC_NZ CC_REGNUM)
2373 (compare:CC_NZ
2374 (plus:GPI
2375 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2376 (match_operand:GPI 2 "register_operand" "rk"))
2377 (const_int 0)))
2378 (set (match_operand:GPI 0 "register_operand" "=r")
2379 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
2380 ""
2381 "adds\\t%<GPI:w>0, %<GPI:w>2, %w1, <su>xt<ALLX:size>"
2382 [(set_attr "type" "alus_ext")]
2383 )
2384
2385 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
2386 [(set (reg:CC_NZ CC_REGNUM)
2387 (compare:CC_NZ
2388 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2389 (ANY_EXTEND:GPI
2390 (match_operand:ALLX 2 "register_operand" "r")))
2391 (const_int 0)))
2392 (set (match_operand:GPI 0 "register_operand" "=r")
2393 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
2394 ""
2395 "subs\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size>"
2396 [(set_attr "type" "alus_ext")]
2397 )
2398
2399 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2400 [(set (reg:CC_NZ CC_REGNUM)
2401 (compare:CC_NZ
2402 (plus:GPI (ashift:GPI
2403 (ANY_EXTEND:GPI
2404 (match_operand:ALLX 1 "register_operand" "r"))
2405 (match_operand 2 "aarch64_imm3" "Ui3"))
2406 (match_operand:GPI 3 "register_operand" "rk"))
2407 (const_int 0)))
2408 (set (match_operand:GPI 0 "register_operand" "=rk")
2409 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
2410 (match_dup 2))
2411 (match_dup 3)))]
2412 ""
2413 "adds\\t%<GPI:w>0, %<GPI:w>3, %w1, <su>xt<ALLX:size> %2"
2414 [(set_attr "type" "alus_ext")]
2415 )
2416
2417 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2418 [(set (reg:CC_NZ CC_REGNUM)
2419 (compare:CC_NZ
2420 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2421 (ashift:GPI
2422 (ANY_EXTEND:GPI
2423 (match_operand:ALLX 2 "register_operand" "r"))
2424 (match_operand 3 "aarch64_imm3" "Ui3")))
2425 (const_int 0)))
2426 (set (match_operand:GPI 0 "register_operand" "=rk")
2427 (minus:GPI (match_dup 1)
2428 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
2429 (match_dup 3))))]
2430 ""
2431 "subs\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size> %3"
2432 [(set_attr "type" "alus_ext")]
2433 )
2434
2435 (define_insn "*add<mode>3nr_compare0"
2436 [(set (reg:CC_NZ CC_REGNUM)
2437 (compare:CC_NZ
2438 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2439 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2440 (const_int 0)))]
2441 ""
2442 "@
2443 cmn\\t%<w>0, %<w>1
2444 cmn\\t%<w>0, %1
2445 cmp\\t%<w>0, #%n1"
2446 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2447 )
2448
2449 (define_insn "aarch64_sub<mode>_compare0"
2450 [(set (reg:CC_NZ CC_REGNUM)
2451 (compare:CC_NZ
2452 (minus:GPI (match_operand:GPI 0 "register_operand" "r")
2453 (match_operand:GPI 1 "aarch64_plus_operand" "r"))
2454 (const_int 0)))]
2455 ""
2456 "cmp\\t%<w>0, %<w>1"
2457 [(set_attr "type" "alus_sreg")]
2458 )
2459
2460 (define_insn "*compare_neg<mode>"
2461 [(set (reg:CC_Z CC_REGNUM)
2462 (compare:CC_Z
2463 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2464 (match_operand:GPI 1 "register_operand" "r")))]
2465 ""
2466 "cmn\\t%<w>1, %<w>0"
2467 [(set_attr "type" "alus_sreg")]
2468 )
2469
2470 (define_insn "*add_<shift>_<mode>"
2471 [(set (match_operand:GPI 0 "register_operand" "=r")
2472 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2473 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2474 (match_operand:GPI 3 "register_operand" "r")))]
2475 ""
2476 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2477 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
2478 )
2479
2480 ;; zero_extend version of above
2481 (define_insn "*add_<shift>_si_uxtw"
2482 [(set (match_operand:DI 0 "register_operand" "=r")
2483 (zero_extend:DI
2484 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2485 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2486 (match_operand:SI 3 "register_operand" "r"))))]
2487 ""
2488 "add\\t%w0, %w3, %w1, <shift> %2"
2489 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
2490 )
2491
2492 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2493 [(set (match_operand:GPI 0 "register_operand" "=rk")
2494 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2495 (match_operand:GPI 2 "register_operand" "r")))]
2496 ""
2497 "add\\t%<GPI:w>0, %<GPI:w>2, %w1, <su>xt<ALLX:size>"
2498 [(set_attr "type" "alu_ext")]
2499 )
2500
2501 ;; zero_extend version of above
2502 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2503 [(set (match_operand:DI 0 "register_operand" "=rk")
2504 (zero_extend:DI
2505 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2506 (match_operand:GPI 2 "register_operand" "r"))))]
2507 ""
2508 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2509 [(set_attr "type" "alu_ext")]
2510 )
2511
2512 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2513 [(set (match_operand:GPI 0 "register_operand" "=rk")
2514 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2515 (match_operand:ALLX 1 "register_operand" "r"))
2516 (match_operand 2 "aarch64_imm3" "Ui3"))
2517 (match_operand:GPI 3 "register_operand" "r")))]
2518 ""
2519 "add\\t%<GPI:w>0, %<GPI:w>3, %w1, <su>xt<ALLX:size> %2"
2520 [(set_attr "type" "alu_ext")]
2521 )
2522
2523 ;; zero_extend version of above
2524 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2525 [(set (match_operand:DI 0 "register_operand" "=rk")
2526 (zero_extend:DI
2527 (plus:SI (ashift:SI (ANY_EXTEND:SI
2528 (match_operand:SHORT 1 "register_operand" "r"))
2529 (match_operand 2 "aarch64_imm3" "Ui3"))
2530 (match_operand:SI 3 "register_operand" "r"))))]
2531 ""
2532 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2533 [(set_attr "type" "alu_ext")]
2534 )
2535
2536 (define_expand "add<mode>3_carryin"
2537 [(set (match_operand:GPI 0 "register_operand")
2538 (plus:GPI
2539 (plus:GPI
2540 (ltu:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2541 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2542 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2543 ""
2544 ""
2545 )
2546
2547 ;; Note that add with carry with two zero inputs is matched by cset,
2548 ;; and that add with carry with one zero input is matched by cinc.
2549
2550 (define_insn "*add<mode>3_carryin"
2551 [(set (match_operand:GPI 0 "register_operand" "=r")
2552 (plus:GPI
2553 (plus:GPI
2554 (match_operand:GPI 3 "aarch64_carry_operation" "")
2555 (match_operand:GPI 1 "register_operand" "r"))
2556 (match_operand:GPI 2 "register_operand" "r")))]
2557 ""
2558 "adc\\t%<w>0, %<w>1, %<w>2"
2559 [(set_attr "type" "adc_reg")]
2560 )
2561
2562 ;; zero_extend version of above
2563 (define_insn "*addsi3_carryin_uxtw"
2564 [(set (match_operand:DI 0 "register_operand" "=r")
2565 (zero_extend:DI
2566 (plus:SI
2567 (plus:SI
2568 (match_operand:SI 3 "aarch64_carry_operation" "")
2569 (match_operand:SI 1 "register_operand" "r"))
2570 (match_operand:SI 2 "register_operand" "r"))))]
2571 ""
2572 "adc\\t%w0, %w1, %w2"
2573 [(set_attr "type" "adc_reg")]
2574 )
2575
2576 (define_expand "add<mode>3_carryinC"
2577 [(parallel
2578 [(set (match_dup 3)
2579 (compare:CC_ADC
2580 (plus:<DWI>
2581 (plus:<DWI>
2582 (match_dup 4)
2583 (zero_extend:<DWI>
2584 (match_operand:GPI 1 "register_operand")))
2585 (zero_extend:<DWI>
2586 (match_operand:GPI 2 "register_operand")))
2587 (match_dup 6)))
2588 (set (match_operand:GPI 0 "register_operand")
2589 (plus:GPI
2590 (plus:GPI (match_dup 5) (match_dup 1))
2591 (match_dup 2)))])]
2592 ""
2593 {
2594 operands[3] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
2595 rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2596 operands[4] = gen_rtx_LTU (<DWI>mode, ccin, const0_rtx);
2597 operands[5] = gen_rtx_LTU (<MODE>mode, ccin, const0_rtx);
2598 operands[6] = immed_wide_int_const (wi::shwi (1, <DWI>mode)
2599 << GET_MODE_BITSIZE (<MODE>mode),
2600 TImode);
2601 })
2602
2603 (define_insn "*add<mode>3_carryinC_zero"
2604 [(set (reg:CC_ADC CC_REGNUM)
2605 (compare:CC_ADC
2606 (plus:<DWI>
2607 (match_operand:<DWI> 2 "aarch64_carry_operation" "")
2608 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2609 (match_operand 4 "const_scalar_int_operand" "")))
2610 (set (match_operand:GPI 0 "register_operand" "=r")
2611 (plus:GPI (match_operand:GPI 3 "aarch64_carry_operation" "")
2612 (match_dup 1)))]
2613 "rtx_mode_t (operands[4], <DWI>mode)
2614 == (wi::shwi (1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2615 "adcs\\t%<w>0, %<w>1, <w>zr"
2616 [(set_attr "type" "adc_reg")]
2617 )
2618
2619 (define_insn "*add<mode>3_carryinC"
2620 [(set (reg:CC_ADC CC_REGNUM)
2621 (compare:CC_ADC
2622 (plus:<DWI>
2623 (plus:<DWI>
2624 (match_operand:<DWI> 3 "aarch64_carry_operation" "")
2625 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2626 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2627 (match_operand 5 "const_scalar_int_operand" "")))
2628 (set (match_operand:GPI 0 "register_operand" "=r")
2629 (plus:GPI
2630 (plus:GPI (match_operand:GPI 4 "aarch64_carry_operation" "")
2631 (match_dup 1))
2632 (match_dup 2)))]
2633 "rtx_mode_t (operands[5], <DWI>mode)
2634 == (wi::shwi (1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2635 "adcs\\t%<w>0, %<w>1, %<w>2"
2636 [(set_attr "type" "adc_reg")]
2637 )
2638
2639 (define_expand "add<mode>3_carryinV"
2640 [(parallel
2641 [(set (reg:CC_V CC_REGNUM)
2642 (compare:CC_V
2643 (plus:<DWI>
2644 (plus:<DWI>
2645 (match_dup 3)
2646 (sign_extend:<DWI>
2647 (match_operand:GPI 1 "register_operand")))
2648 (sign_extend:<DWI>
2649 (match_operand:GPI 2 "register_operand")))
2650 (sign_extend:<DWI>
2651 (plus:GPI
2652 (plus:GPI (match_dup 4) (match_dup 1))
2653 (match_dup 2)))))
2654 (set (match_operand:GPI 0 "register_operand")
2655 (plus:GPI
2656 (plus:GPI (match_dup 4) (match_dup 1))
2657 (match_dup 2)))])]
2658 ""
2659 {
2660 rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2661 operands[3] = gen_rtx_LTU (<DWI>mode, cc, const0_rtx);
2662 operands[4] = gen_rtx_LTU (<MODE>mode, cc, const0_rtx);
2663 })
2664
2665 (define_insn "*add<mode>3_carryinV_zero"
2666 [(set (reg:CC_V CC_REGNUM)
2667 (compare:CC_V
2668 (plus:<DWI>
2669 (match_operand:<DWI> 2 "aarch64_carry_operation" "")
2670 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2671 (sign_extend:<DWI>
2672 (plus:GPI
2673 (match_operand:GPI 3 "aarch64_carry_operation" "")
2674 (match_dup 1)))))
2675 (set (match_operand:GPI 0 "register_operand" "=r")
2676 (plus:GPI (match_dup 3) (match_dup 1)))]
2677 ""
2678 "adcs\\t%<w>0, %<w>1, <w>zr"
2679 [(set_attr "type" "adc_reg")]
2680 )
2681
2682 (define_insn "*add<mode>3_carryinV"
2683 [(set (reg:CC_V CC_REGNUM)
2684 (compare:CC_V
2685 (plus:<DWI>
2686 (plus:<DWI>
2687 (match_operand:<DWI> 3 "aarch64_carry_operation" "")
2688 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2689 (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2690 (sign_extend:<DWI>
2691 (plus:GPI
2692 (plus:GPI
2693 (match_operand:GPI 4 "aarch64_carry_operation" "")
2694 (match_dup 1))
2695 (match_dup 2)))))
2696 (set (match_operand:GPI 0 "register_operand" "=r")
2697 (plus:GPI
2698 (plus:GPI (match_dup 4) (match_dup 1))
2699 (match_dup 2)))]
2700 ""
2701 "adcs\\t%<w>0, %<w>1, %<w>2"
2702 [(set_attr "type" "adc_reg")]
2703 )
2704
2705 (define_insn "*add_uxt<mode>_shift2"
2706 [(set (match_operand:GPI 0 "register_operand" "=rk")
2707 (plus:GPI (and:GPI
2708 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2709 (match_operand 2 "aarch64_imm3" "Ui3"))
2710 (match_operand 3 "const_int_operand" "n"))
2711 (match_operand:GPI 4 "register_operand" "r")))]
2712 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2713 "*
2714 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2715 INTVAL (operands[3])));
2716 return \"add\t%<w>0, %<w>4, %w1, uxt%e3 %2\";"
2717 [(set_attr "type" "alu_ext")]
2718 )
2719
2720 ;; zero_extend version of above
2721 (define_insn "*add_uxtsi_shift2_uxtw"
2722 [(set (match_operand:DI 0 "register_operand" "=rk")
2723 (zero_extend:DI
2724 (plus:SI (and:SI
2725 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2726 (match_operand 2 "aarch64_imm3" "Ui3"))
2727 (match_operand 3 "const_int_operand" "n"))
2728 (match_operand:SI 4 "register_operand" "r"))))]
2729 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2730 "*
2731 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2732 INTVAL (operands[3])));
2733 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2734 [(set_attr "type" "alu_ext")]
2735 )
2736
2737 (define_insn "subsi3"
2738 [(set (match_operand:SI 0 "register_operand" "=rk")
2739 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2740 (match_operand:SI 2 "register_operand" "r")))]
2741 ""
2742 "sub\\t%w0, %w1, %w2"
2743 [(set_attr "type" "alu_sreg")]
2744 )
2745
2746 ;; zero_extend version of above
2747 (define_insn "*subsi3_uxtw"
2748 [(set (match_operand:DI 0 "register_operand" "=rk")
2749 (zero_extend:DI
2750 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2751 (match_operand:SI 2 "register_operand" "r"))))]
2752 ""
2753 "sub\\t%w0, %w1, %w2"
2754 [(set_attr "type" "alu_sreg")]
2755 )
2756
2757 (define_insn "subdi3"
2758 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2759 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2760 (match_operand:DI 2 "register_operand" "r,w")))]
2761 ""
2762 "@
2763 sub\\t%x0, %x1, %x2
2764 sub\\t%d0, %d1, %d2"
2765 [(set_attr "type" "alu_sreg, neon_sub")
2766 (set_attr "arch" "*,simd")]
2767 )
2768
2769 (define_expand "subv<GPI:mode>4"
2770 [(match_operand:GPI 0 "register_operand")
2771 (match_operand:GPI 1 "register_operand")
2772 (match_operand:GPI 2 "aarch64_plus_operand")
2773 (label_ref (match_operand 3 "" ""))]
2774 ""
2775 {
2776 if (CONST_INT_P (operands[2]))
2777 emit_insn (gen_subv<mode>_imm (operands[0], operands[1], operands[2]));
2778 else
2779 emit_insn (gen_subv<mode>_insn (operands[0], operands[1], operands[2]));
2780 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2781
2782 DONE;
2783 })
2784
2785 (define_insn "subv<GPI:mode>_insn"
2786 [(set (reg:CC_V CC_REGNUM)
2787 (compare:CC_V
2788 (sign_extend:<DWI>
2789 (minus:GPI
2790 (match_operand:GPI 1 "register_operand" "rk")
2791 (match_operand:GPI 2 "register_operand" "r")))
2792 (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
2793 (sign_extend:<DWI> (match_dup 2)))))
2794 (set (match_operand:GPI 0 "register_operand" "=r")
2795 (minus:GPI (match_dup 1) (match_dup 2)))]
2796 ""
2797 "subs\\t%<w>0, %<w>1, %<w>2"
2798 [(set_attr "type" "alus_sreg")]
2799 )
2800
2801 (define_insn "subv<GPI:mode>_imm"
2802 [(set (reg:CC_V CC_REGNUM)
2803 (compare:CC_V
2804 (sign_extend:<DWI>
2805 (minus:GPI
2806 (match_operand:GPI 1 "register_operand" "rk,rk")
2807 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))
2808 (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
2809 (match_dup 2))))
2810 (set (match_operand:GPI 0 "register_operand" "=r,r")
2811 (minus:GPI (match_dup 1) (match_dup 2)))]
2812 ""
2813 "@
2814 subs\\t%<w>0, %<w>1, %2
2815 adds\\t%<w>0, %<w>1, #%n2"
2816 [(set_attr "type" "alus_sreg")]
2817 )
2818
2819 (define_expand "negv<GPI:mode>3"
2820 [(match_operand:GPI 0 "register_operand")
2821 (match_operand:GPI 1 "register_operand")
2822 (label_ref (match_operand 2 "" ""))]
2823 ""
2824 {
2825 emit_insn (gen_negv<mode>_insn (operands[0], operands[1]));
2826 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
2827
2828 DONE;
2829 }
2830 )
2831
2832 (define_insn "negv<GPI:mode>_insn"
2833 [(set (reg:CC_V CC_REGNUM)
2834 (compare:CC_V
2835 (sign_extend:<DWI>
2836 (neg:GPI (match_operand:GPI 1 "register_operand" "r")))
2837 (neg:<DWI> (sign_extend:<DWI> (match_dup 1)))))
2838 (set (match_operand:GPI 0 "register_operand" "=r")
2839 (neg:GPI (match_dup 1)))]
2840 ""
2841 "negs\\t%<w>0, %<w>1"
2842 [(set_attr "type" "alus_sreg")]
2843 )
2844
2845 (define_insn "negv<GPI:mode>_cmp_only"
2846 [(set (reg:CC_V CC_REGNUM)
2847 (compare:CC_V
2848 (sign_extend:<DWI>
2849 (neg:GPI (match_operand:GPI 0 "register_operand" "r")))
2850 (neg:<DWI> (sign_extend:<DWI> (match_dup 0)))))]
2851 ""
2852 "negs\\t%<w>zr, %<w>0"
2853 [(set_attr "type" "alus_sreg")]
2854 )
2855
2856 (define_insn "*cmpv<GPI:mode>_insn"
2857 [(set (reg:CC_V CC_REGNUM)
2858 (compare:CC_V
2859 (sign_extend:<DWI>
2860 (minus:GPI (match_operand:GPI 0 "register_operand" "r,r,r")
2861 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))
2862 (minus:<DWI> (sign_extend:<DWI> (match_dup 0))
2863 (sign_extend:<DWI> (match_dup 1)))))]
2864 ""
2865 "@
2866 cmp\\t%<w>0, %<w>1
2867 cmp\\t%<w>0, %1
2868 cmp\\t%<w>0, #%n1"
2869 [(set_attr "type" "alus_sreg")]
2870 )
2871
2872 (define_expand "usubv<mode>4"
2873 [(match_operand:GPI 0 "register_operand")
2874 (match_operand:GPI 1 "aarch64_reg_or_zero")
2875 (match_operand:GPI 2 "aarch64_reg_or_zero")
2876 (label_ref (match_operand 3 "" ""))]
2877 ""
2878 {
2879 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
2880 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
2881
2882 DONE;
2883 })
2884
2885 (define_expand "subti3"
2886 [(set (match_operand:TI 0 "register_operand")
2887 (minus:TI (match_operand:TI 1 "aarch64_reg_or_zero")
2888 (match_operand:TI 2 "register_operand")))]
2889 ""
2890 {
2891 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2892
2893 aarch64_subvti_scratch_regs (operands[1], operands[2],
2894 &low_dest, &op1_low, &op2_low,
2895 &high_dest, &op1_high, &op2_high);
2896
2897 emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low));
2898 emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high));
2899
2900 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2901 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2902 DONE;
2903 })
2904
2905 (define_expand "subvti4"
2906 [(match_operand:TI 0 "register_operand")
2907 (match_operand:TI 1 "register_operand")
2908 (match_operand:TI 2 "aarch64_reg_or_imm")
2909 (label_ref (match_operand 3 "" ""))]
2910 ""
2911 {
2912 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2913
2914 aarch64_subvti_scratch_regs (operands[1], operands[2],
2915 &low_dest, &op1_low, &op2_low,
2916 &high_dest, &op1_high, &op2_high);
2917 aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
2918 high_dest, op1_high, op2_high, false);
2919
2920 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2921 DONE;
2922 })
2923
2924 (define_expand "usubvti4"
2925 [(match_operand:TI 0 "register_operand")
2926 (match_operand:TI 1 "register_operand")
2927 (match_operand:TI 2 "aarch64_reg_or_imm")
2928 (label_ref (match_operand 3 "" ""))]
2929 ""
2930 {
2931 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2932
2933 aarch64_subvti_scratch_regs (operands[1], operands[2],
2934 &low_dest, &op1_low, &op2_low,
2935 &high_dest, &op1_high, &op2_high);
2936 aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
2937 high_dest, op1_high, op2_high, true);
2938
2939 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
2940 DONE;
2941 })
2942
2943 (define_expand "negvti3"
2944 [(match_operand:TI 0 "register_operand")
2945 (match_operand:TI 1 "register_operand")
2946 (label_ref (match_operand 2 "" ""))]
2947 ""
2948 {
2949 emit_insn (gen_negdi_carryout (gen_lowpart (DImode, operands[0]),
2950 gen_lowpart (DImode, operands[1])));
2951 emit_insn (gen_negvdi_carryinV (gen_highpart (DImode, operands[0]),
2952 gen_highpart (DImode, operands[1])));
2953 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
2954
2955 DONE;
2956 }
2957 )
2958
2959 (define_insn "negdi_carryout"
2960 [(set (reg:CC CC_REGNUM)
2961 (compare:CC
2962 (const_int 0) (match_operand:DI 1 "register_operand" "r")))
2963 (set (match_operand:DI 0 "register_operand" "=r")
2964 (neg:DI (match_dup 1)))]
2965 ""
2966 "negs\\t%0, %1"
2967 [(set_attr "type" "alus_sreg")]
2968 )
2969
2970 (define_insn "negvdi_carryinV"
2971 [(set (reg:CC_V CC_REGNUM)
2972 (compare:CC_V
2973 (neg:TI (plus:TI
2974 (ltu:TI (reg:CC CC_REGNUM) (const_int 0))
2975 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))))
2976 (sign_extend:TI
2977 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
2978 (match_dup 1))))))
2979 (set (match_operand:DI 0 "register_operand" "=r")
2980 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
2981 (match_dup 1))))]
2982 ""
2983 "ngcs\\t%0, %1"
2984 [(set_attr "type" "alus_sreg")]
2985 )
2986
2987 (define_insn "*sub<mode>3_compare0"
2988 [(set (reg:CC_NZ CC_REGNUM)
2989 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2990 (match_operand:GPI 2 "register_operand" "r"))
2991 (const_int 0)))
2992 (set (match_operand:GPI 0 "register_operand" "=r")
2993 (minus:GPI (match_dup 1) (match_dup 2)))]
2994 ""
2995 "subs\\t%<w>0, %<w>1, %<w>2"
2996 [(set_attr "type" "alus_sreg")]
2997 )
2998
2999 ;; zero_extend version of above
3000 (define_insn "*subsi3_compare0_uxtw"
3001 [(set (reg:CC_NZ CC_REGNUM)
3002 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "rk")
3003 (match_operand:SI 2 "register_operand" "r"))
3004 (const_int 0)))
3005 (set (match_operand:DI 0 "register_operand" "=r")
3006 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
3007 ""
3008 "subs\\t%w0, %w1, %w2"
3009 [(set_attr "type" "alus_sreg")]
3010 )
3011
3012 (define_insn "sub<mode>3_compare1_imm"
3013 [(set (reg:CC CC_REGNUM)
3014 (compare:CC
3015 (match_operand:GPI 1 "aarch64_reg_or_zero" "rkZ,rkZ")
3016 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))
3017 (set (match_operand:GPI 0 "register_operand" "=r,r")
3018 (plus:GPI
3019 (match_dup 1)
3020 (match_operand:GPI 3 "aarch64_plus_immediate" "J,I")))]
3021 "UINTVAL (operands[2]) == -UINTVAL (operands[3])"
3022 "@
3023 subs\\t%<w>0, %<w>1, %2
3024 adds\\t%<w>0, %<w>1, #%n2"
3025 [(set_attr "type" "alus_imm")]
3026 )
3027
3028 (define_insn "sub<mode>3_compare1"
3029 [(set (reg:CC CC_REGNUM)
3030 (compare:CC
3031 (match_operand:GPI 1 "aarch64_reg_or_zero" "rkZ")
3032 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
3033 (set (match_operand:GPI 0 "register_operand" "=r")
3034 (minus:GPI (match_dup 1) (match_dup 2)))]
3035 ""
3036 "subs\\t%<w>0, %<w>1, %<w>2"
3037 [(set_attr "type" "alus_sreg")]
3038 )
3039
3040 (define_peephole2
3041 [(set (match_operand:GPI 0 "aarch64_general_reg")
3042 (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
3043 (match_operand:GPI 2 "aarch64_reg_or_zero")))
3044 (set (reg:CC CC_REGNUM)
3045 (compare:CC
3046 (match_dup 1)
3047 (match_dup 2)))]
3048 "!reg_overlap_mentioned_p (operands[0], operands[1])
3049 && !reg_overlap_mentioned_p (operands[0], operands[2])"
3050 [(const_int 0)]
3051 {
3052 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
3053 operands[2]));
3054 DONE;
3055 }
3056 )
3057
3058 ;; Same as the above peephole but with the compare and minus in
3059 ;; swapped order. The restriction on overlap between operand 0
3060 ;; and operands 1 and 2 doesn't apply here.
3061 (define_peephole2
3062 [(set (reg:CC CC_REGNUM)
3063 (compare:CC
3064 (match_operand:GPI 1 "aarch64_reg_or_zero")
3065 (match_operand:GPI 2 "aarch64_reg_or_zero")))
3066 (set (match_operand:GPI 0 "aarch64_general_reg")
3067 (minus:GPI (match_dup 1)
3068 (match_dup 2)))]
3069 ""
3070 [(const_int 0)]
3071 {
3072 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
3073 operands[2]));
3074 DONE;
3075 }
3076 )
3077
3078 (define_peephole2
3079 [(set (match_operand:GPI 0 "aarch64_general_reg")
3080 (plus:GPI (match_operand:GPI 1 "register_operand")
3081 (match_operand:GPI 2 "aarch64_plus_immediate")))
3082 (set (reg:CC CC_REGNUM)
3083 (compare:CC
3084 (match_dup 1)
3085 (match_operand:GPI 3 "const_int_operand")))]
3086 "!reg_overlap_mentioned_p (operands[0], operands[1])
3087 && INTVAL (operands[3]) == -INTVAL (operands[2])"
3088 [(const_int 0)]
3089 {
3090 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3091 operands[3], operands[2]));
3092 DONE;
3093 }
3094 )
3095
3096 ;; Same as the above peephole but with the compare and minus in
3097 ;; swapped order. The restriction on overlap between operand 0
3098 ;; and operands 1 doesn't apply here.
3099 (define_peephole2
3100 [(set (reg:CC CC_REGNUM)
3101 (compare:CC
3102 (match_operand:GPI 1 "register_operand")
3103 (match_operand:GPI 3 "const_int_operand")))
3104 (set (match_operand:GPI 0 "aarch64_general_reg")
3105 (plus:GPI (match_dup 1)
3106 (match_operand:GPI 2 "aarch64_plus_immediate")))]
3107 "INTVAL (operands[3]) == -INTVAL (operands[2])"
3108 [(const_int 0)]
3109 {
3110 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3111 operands[3], operands[2]));
3112 DONE;
3113 }
3114 )
3115
3116 (define_insn "*sub_<shift>_<mode>"
3117 [(set (match_operand:GPI 0 "register_operand" "=r")
3118 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
3119 (ASHIFT:GPI
3120 (match_operand:GPI 1 "register_operand" "r")
3121 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3122 ""
3123 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
3124 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3125 )
3126
3127 ;; zero_extend version of above
3128 (define_insn "*sub_<shift>_si_uxtw"
3129 [(set (match_operand:DI 0 "register_operand" "=r")
3130 (zero_extend:DI
3131 (minus:SI (match_operand:SI 3 "register_operand" "r")
3132 (ASHIFT:SI
3133 (match_operand:SI 1 "register_operand" "r")
3134 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
3135 ""
3136 "sub\\t%w0, %w3, %w1, <shift> %2"
3137 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3138 )
3139
3140 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
3141 [(set (match_operand:GPI 0 "register_operand" "=rk")
3142 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
3143 (ANY_EXTEND:GPI
3144 (match_operand:ALLX 2 "register_operand" "r"))))]
3145 ""
3146 "sub\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size>"
3147 [(set_attr "type" "alu_ext")]
3148 )
3149
3150 ;; zero_extend version of above
3151 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
3152 [(set (match_operand:DI 0 "register_operand" "=rk")
3153 (zero_extend:DI
3154 (minus:SI (match_operand:SI 1 "register_operand" "rk")
3155 (ANY_EXTEND:SI
3156 (match_operand:SHORT 2 "register_operand" "r")))))]
3157 ""
3158 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
3159 [(set_attr "type" "alu_ext")]
3160 )
3161
3162 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
3163 [(set (match_operand:GPI 0 "register_operand" "=rk")
3164 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
3165 (ashift:GPI (ANY_EXTEND:GPI
3166 (match_operand:ALLX 2 "register_operand" "r"))
3167 (match_operand 3 "aarch64_imm3" "Ui3"))))]
3168 ""
3169 "sub\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size> %3"
3170 [(set_attr "type" "alu_ext")]
3171 )
3172
3173 ;; zero_extend version of above
3174 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
3175 [(set (match_operand:DI 0 "register_operand" "=rk")
3176 (zero_extend:DI
3177 (minus:SI (match_operand:SI 1 "register_operand" "rk")
3178 (ashift:SI (ANY_EXTEND:SI
3179 (match_operand:SHORT 2 "register_operand" "r"))
3180 (match_operand 3 "aarch64_imm3" "Ui3")))))]
3181 ""
3182 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
3183 [(set_attr "type" "alu_ext")]
3184 )
3185
3186 ;; The hardware description is op1 + ~op2 + C.
3187 ;; = op1 + (-op2 + 1) + (1 - !C)
3188 ;; = op1 - op2 - 1 + 1 - !C
3189 ;; = op1 - op2 - !C.
3190 ;; We describe the latter.
3191
3192 (define_insn "*sub<mode>3_carryin0"
3193 [(set (match_operand:GPI 0 "register_operand" "=r")
3194 (minus:GPI
3195 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3196 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
3197 ""
3198 "sbc\\t%<w>0, %<w>1, <w>zr"
3199 [(set_attr "type" "adc_reg")]
3200 )
3201
3202 ;; zero_extend version of the above
3203 (define_insn "*subsi3_carryin_uxtw"
3204 [(set (match_operand:DI 0 "register_operand" "=r")
3205 (zero_extend:DI
3206 (minus:SI
3207 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3208 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
3209 ""
3210 "sbc\\t%w0, %w1, wzr"
3211 [(set_attr "type" "adc_reg")]
3212 )
3213
3214 (define_expand "sub<mode>3_carryin"
3215 [(set (match_operand:GPI 0 "register_operand")
3216 (minus:GPI
3217 (minus:GPI
3218 (match_operand:GPI 1 "aarch64_reg_or_zero")
3219 (match_operand:GPI 2 "register_operand"))
3220 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
3221 ""
3222 ""
3223 )
3224
3225 (define_insn "*sub<mode>3_carryin"
3226 [(set (match_operand:GPI 0 "register_operand" "=r")
3227 (minus:GPI
3228 (minus:GPI
3229 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3230 (match_operand:GPI 2 "register_operand" "r"))
3231 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3232
3233 ""
3234 "sbc\\t%<w>0, %<w>1, %<w>2"
3235 [(set_attr "type" "adc_reg")]
3236 )
3237
3238 ;; zero_extend version of the above
3239 (define_insn "*subsi3_carryin_uxtw"
3240 [(set (match_operand:DI 0 "register_operand" "=r")
3241 (zero_extend:DI
3242 (minus:SI
3243 (minus:SI
3244 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3245 (match_operand:SI 2 "register_operand" "r"))
3246 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
3247
3248 ""
3249 "sbc\\t%w0, %w1, %w2"
3250 [(set_attr "type" "adc_reg")]
3251 )
3252
3253 (define_insn "*sub<mode>3_carryin_alt"
3254 [(set (match_operand:GPI 0 "register_operand" "=r")
3255 (minus:GPI
3256 (minus:GPI
3257 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3258 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
3259 (match_operand:GPI 2 "register_operand" "r")))]
3260 ""
3261 "sbc\\t%<w>0, %<w>1, %<w>2"
3262 [(set_attr "type" "adc_reg")]
3263 )
3264
3265 ;; zero_extend version of the above
3266 (define_insn "*subsi3_carryin_alt_uxtw"
3267 [(set (match_operand:DI 0 "register_operand" "=r")
3268 (zero_extend:DI
3269 (minus:SI
3270 (minus:SI
3271 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3272 (match_operand:SI 3 "aarch64_borrow_operation" ""))
3273 (match_operand:SI 2 "register_operand" "r"))))]
3274 ""
3275 "sbc\\t%w0, %w1, %w2"
3276 [(set_attr "type" "adc_reg")]
3277 )
3278
3279 (define_expand "usub<GPI:mode>3_carryinC"
3280 [(parallel
3281 [(set (reg:CC CC_REGNUM)
3282 (compare:CC
3283 (zero_extend:<DWI>
3284 (match_operand:GPI 1 "aarch64_reg_or_zero"))
3285 (plus:<DWI>
3286 (zero_extend:<DWI>
3287 (match_operand:GPI 2 "register_operand"))
3288 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0)))))
3289 (set (match_operand:GPI 0 "register_operand")
3290 (minus:GPI
3291 (minus:GPI (match_dup 1) (match_dup 2))
3292 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3293 ""
3294 )
3295
3296 (define_insn "*usub<GPI:mode>3_carryinC_z1"
3297 [(set (reg:CC CC_REGNUM)
3298 (compare:CC
3299 (const_int 0)
3300 (plus:<DWI>
3301 (zero_extend:<DWI>
3302 (match_operand:GPI 1 "register_operand" "r"))
3303 (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))))
3304 (set (match_operand:GPI 0 "register_operand" "=r")
3305 (minus:GPI
3306 (neg:GPI (match_dup 1))
3307 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3308 ""
3309 "sbcs\\t%<w>0, <w>zr, %<w>1"
3310 [(set_attr "type" "adc_reg")]
3311 )
3312
3313 (define_insn "*usub<GPI:mode>3_carryinC_z2"
3314 [(set (reg:CC CC_REGNUM)
3315 (compare:CC
3316 (zero_extend:<DWI>
3317 (match_operand:GPI 1 "register_operand" "r"))
3318 (match_operand:<DWI> 2 "aarch64_borrow_operation" "")))
3319 (set (match_operand:GPI 0 "register_operand" "=r")
3320 (minus:GPI
3321 (match_dup 1)
3322 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3323 ""
3324 "sbcs\\t%<w>0, %<w>1, <w>zr"
3325 [(set_attr "type" "adc_reg")]
3326 )
3327
3328 (define_insn "*usub<GPI:mode>3_carryinC"
3329 [(set (reg:CC CC_REGNUM)
3330 (compare:CC
3331 (zero_extend:<DWI>
3332 (match_operand:GPI 1 "register_operand" "r"))
3333 (plus:<DWI>
3334 (zero_extend:<DWI>
3335 (match_operand:GPI 2 "register_operand" "r"))
3336 (match_operand:<DWI> 3 "aarch64_borrow_operation" ""))))
3337 (set (match_operand:GPI 0 "register_operand" "=r")
3338 (minus:GPI
3339 (minus:GPI (match_dup 1) (match_dup 2))
3340 (match_operand:GPI 4 "aarch64_borrow_operation" "")))]
3341 ""
3342 "sbcs\\t%<w>0, %<w>1, %<w>2"
3343 [(set_attr "type" "adc_reg")]
3344 )
3345
3346 (define_expand "sub<GPI:mode>3_carryinV"
3347 [(parallel
3348 [(set (reg:CC_V CC_REGNUM)
3349 (compare:CC_V
3350 (minus:<DWI>
3351 (sign_extend:<DWI>
3352 (match_operand:GPI 1 "aarch64_reg_or_zero"))
3353 (plus:<DWI>
3354 (sign_extend:<DWI>
3355 (match_operand:GPI 2 "register_operand"))
3356 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0))))
3357 (sign_extend:<DWI>
3358 (minus:GPI (match_dup 1)
3359 (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))
3360 (match_dup 2))))))
3361 (set (match_operand:GPI 0 "register_operand")
3362 (minus:GPI
3363 (minus:GPI (match_dup 1) (match_dup 2))
3364 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3365 ""
3366 )
3367
3368 (define_insn "*sub<mode>3_carryinV_z2"
3369 [(set (reg:CC_V CC_REGNUM)
3370 (compare:CC_V
3371 (minus:<DWI>
3372 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
3373 (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))
3374 (sign_extend:<DWI>
3375 (minus:GPI (match_dup 1)
3376 (match_operand:GPI 3 "aarch64_borrow_operation" "")))))
3377 (set (match_operand:GPI 0 "register_operand" "=r")
3378 (minus:GPI
3379 (match_dup 1) (match_dup 3)))]
3380 ""
3381 "sbcs\\t%<w>0, %<w>1, <w>zr"
3382 [(set_attr "type" "adc_reg")]
3383 )
3384
3385 (define_insn "*sub<mode>3_carryinV"
3386 [(set (reg:CC_V CC_REGNUM)
3387 (compare:CC_V
3388 (minus:<DWI>
3389 (sign_extend:<DWI>
3390 (match_operand:GPI 1 "register_operand" "r"))
3391 (plus:<DWI>
3392 (sign_extend:<DWI>
3393 (match_operand:GPI 2 "register_operand" "r"))
3394 (match_operand:<DWI> 3 "aarch64_borrow_operation" "")))
3395 (sign_extend:<DWI>
3396 (minus:GPI
3397 (match_dup 1)
3398 (plus:GPI (match_operand:GPI 4 "aarch64_borrow_operation" "")
3399 (match_dup 2))))))
3400 (set (match_operand:GPI 0 "register_operand" "=r")
3401 (minus:GPI
3402 (minus:GPI (match_dup 1) (match_dup 2))
3403 (match_dup 4)))]
3404 ""
3405 "sbcs\\t%<w>0, %<w>1, %<w>2"
3406 [(set_attr "type" "adc_reg")]
3407 )
3408
3409 (define_insn "*sub_uxt<mode>_shift2"
3410 [(set (match_operand:GPI 0 "register_operand" "=rk")
3411 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
3412 (and:GPI
3413 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3414 (match_operand 2 "aarch64_imm3" "Ui3"))
3415 (match_operand 3 "const_int_operand" "n"))))]
3416 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
3417 "*
3418 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
3419 INTVAL (operands[3])));
3420 return \"sub\t%<w>0, %<w>4, %w1, uxt%e3 %2\";"
3421 [(set_attr "type" "alu_ext")]
3422 )
3423
3424 ;; zero_extend version of above
3425 (define_insn "*sub_uxtsi_shift2_uxtw"
3426 [(set (match_operand:DI 0 "register_operand" "=rk")
3427 (zero_extend:DI
3428 (minus:SI (match_operand:SI 4 "register_operand" "rk")
3429 (and:SI
3430 (ashift:SI (match_operand:SI 1 "register_operand" "r")
3431 (match_operand 2 "aarch64_imm3" "Ui3"))
3432 (match_operand 3 "const_int_operand" "n")))))]
3433 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
3434 "*
3435 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
3436 INTVAL (operands[3])));
3437 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
3438 [(set_attr "type" "alu_ext")]
3439 )
3440
3441 (define_expand "abs<mode>2"
3442 [(match_operand:GPI 0 "register_operand")
3443 (match_operand:GPI 1 "register_operand")]
3444 ""
3445 {
3446 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
3447 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
3448 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
3449 DONE;
3450 }
3451 )
3452
3453 (define_insn "neg<mode>2"
3454 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3455 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3456 ""
3457 "@
3458 neg\\t%<w>0, %<w>1
3459 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
3460 [(set_attr "type" "alu_sreg, neon_neg<q>")
3461 (set_attr "arch" "*,simd")]
3462 )
3463
3464 ;; zero_extend version of above
3465 (define_insn "*negsi2_uxtw"
3466 [(set (match_operand:DI 0 "register_operand" "=r")
3467 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
3468 ""
3469 "neg\\t%w0, %w1"
3470 [(set_attr "type" "alu_sreg")]
3471 )
3472
3473 (define_insn "*ngc<mode>"
3474 [(set (match_operand:GPI 0 "register_operand" "=r")
3475 (minus:GPI
3476 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
3477 (match_operand:GPI 1 "register_operand" "r")))]
3478 ""
3479 "ngc\\t%<w>0, %<w>1"
3480 [(set_attr "type" "adc_reg")]
3481 )
3482
3483 (define_insn "*ngcsi_uxtw"
3484 [(set (match_operand:DI 0 "register_operand" "=r")
3485 (zero_extend:DI
3486 (minus:SI
3487 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
3488 (match_operand:SI 1 "register_operand" "r"))))]
3489 ""
3490 "ngc\\t%w0, %w1"
3491 [(set_attr "type" "adc_reg")]
3492 )
3493
3494 (define_insn "neg<mode>2_compare0"
3495 [(set (reg:CC_NZ CC_REGNUM)
3496 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
3497 (const_int 0)))
3498 (set (match_operand:GPI 0 "register_operand" "=r")
3499 (neg:GPI (match_dup 1)))]
3500 ""
3501 "negs\\t%<w>0, %<w>1"
3502 [(set_attr "type" "alus_sreg")]
3503 )
3504
3505 ;; zero_extend version of above
3506 (define_insn "*negsi2_compare0_uxtw"
3507 [(set (reg:CC_NZ CC_REGNUM)
3508 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
3509 (const_int 0)))
3510 (set (match_operand:DI 0 "register_operand" "=r")
3511 (zero_extend:DI (neg:SI (match_dup 1))))]
3512 ""
3513 "negs\\t%w0, %w1"
3514 [(set_attr "type" "alus_sreg")]
3515 )
3516
3517 (define_insn "*neg_<shift><mode>3_compare0"
3518 [(set (reg:CC_NZ CC_REGNUM)
3519 (compare:CC_NZ
3520 (neg:GPI (ASHIFT:GPI
3521 (match_operand:GPI 1 "register_operand" "r")
3522 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3523 (const_int 0)))
3524 (set (match_operand:GPI 0 "register_operand" "=r")
3525 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
3526 ""
3527 "negs\\t%<w>0, %<w>1, <shift> %2"
3528 [(set_attr "type" "alus_shift_imm")]
3529 )
3530
3531 (define_insn "*neg_<shift>_<mode>2"
3532 [(set (match_operand:GPI 0 "register_operand" "=r")
3533 (neg:GPI (ASHIFT:GPI
3534 (match_operand:GPI 1 "register_operand" "r")
3535 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3536 ""
3537 "neg\\t%<w>0, %<w>1, <shift> %2"
3538 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3539 )
3540
3541 ;; zero_extend version of above
3542 (define_insn "*neg_<shift>_si2_uxtw"
3543 [(set (match_operand:DI 0 "register_operand" "=r")
3544 (zero_extend:DI
3545 (neg:SI (ASHIFT:SI
3546 (match_operand:SI 1 "register_operand" "r")
3547 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
3548 ""
3549 "neg\\t%w0, %w1, <shift> %2"
3550 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3551 )
3552
3553 (define_insn "mul<mode>3"
3554 [(set (match_operand:GPI 0 "register_operand" "=r")
3555 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3556 (match_operand:GPI 2 "register_operand" "r")))]
3557 ""
3558 "mul\\t%<w>0, %<w>1, %<w>2"
3559 [(set_attr "type" "mul")]
3560 )
3561
3562 ;; zero_extend version of above
3563 (define_insn "*mulsi3_uxtw"
3564 [(set (match_operand:DI 0 "register_operand" "=r")
3565 (zero_extend:DI
3566 (mult:SI (match_operand:SI 1 "register_operand" "r")
3567 (match_operand:SI 2 "register_operand" "r"))))]
3568 ""
3569 "mul\\t%w0, %w1, %w2"
3570 [(set_attr "type" "mul")]
3571 )
3572
3573 (define_insn "madd<mode>"
3574 [(set (match_operand:GPI 0 "register_operand" "=r")
3575 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3576 (match_operand:GPI 2 "register_operand" "r"))
3577 (match_operand:GPI 3 "register_operand" "r")))]
3578 ""
3579 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
3580 [(set_attr "type" "mla")]
3581 )
3582
3583 ;; zero_extend version of above
3584 (define_insn "*maddsi_uxtw"
3585 [(set (match_operand:DI 0 "register_operand" "=r")
3586 (zero_extend:DI
3587 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
3588 (match_operand:SI 2 "register_operand" "r"))
3589 (match_operand:SI 3 "register_operand" "r"))))]
3590 ""
3591 "madd\\t%w0, %w1, %w2, %w3"
3592 [(set_attr "type" "mla")]
3593 )
3594
3595 (define_insn "*msub<mode>"
3596 [(set (match_operand:GPI 0 "register_operand" "=r")
3597 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
3598 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3599 (match_operand:GPI 2 "register_operand" "r"))))]
3600
3601 ""
3602 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
3603 [(set_attr "type" "mla")]
3604 )
3605
3606 ;; zero_extend version of above
3607 (define_insn "*msubsi_uxtw"
3608 [(set (match_operand:DI 0 "register_operand" "=r")
3609 (zero_extend:DI
3610 (minus:SI (match_operand:SI 3 "register_operand" "r")
3611 (mult:SI (match_operand:SI 1 "register_operand" "r")
3612 (match_operand:SI 2 "register_operand" "r")))))]
3613
3614 ""
3615 "msub\\t%w0, %w1, %w2, %w3"
3616 [(set_attr "type" "mla")]
3617 )
3618
3619 (define_insn "*mul<mode>_neg"
3620 [(set (match_operand:GPI 0 "register_operand" "=r")
3621 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
3622 (match_operand:GPI 2 "register_operand" "r")))]
3623
3624 ""
3625 "mneg\\t%<w>0, %<w>1, %<w>2"
3626 [(set_attr "type" "mul")]
3627 )
3628
3629 ;; zero_extend version of above
3630 (define_insn "*mulsi_neg_uxtw"
3631 [(set (match_operand:DI 0 "register_operand" "=r")
3632 (zero_extend:DI
3633 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
3634 (match_operand:SI 2 "register_operand" "r"))))]
3635
3636 ""
3637 "mneg\\t%w0, %w1, %w2"
3638 [(set_attr "type" "mul")]
3639 )
3640
3641 (define_insn "<su_optab>mulsidi3"
3642 [(set (match_operand:DI 0 "register_operand" "=r")
3643 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
3644 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
3645 ""
3646 "<su>mull\\t%0, %w1, %w2"
3647 [(set_attr "type" "<su>mull")]
3648 )
3649
3650 (define_insn "<su_optab>maddsidi4"
3651 [(set (match_operand:DI 0 "register_operand" "=r")
3652 (plus:DI (mult:DI
3653 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
3654 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
3655 (match_operand:DI 3 "register_operand" "r")))]
3656 ""
3657 "<su>maddl\\t%0, %w1, %w2, %3"
3658 [(set_attr "type" "<su>mlal")]
3659 )
3660
3661 (define_insn "<su_optab>msubsidi4"
3662 [(set (match_operand:DI 0 "register_operand" "=r")
3663 (minus:DI
3664 (match_operand:DI 3 "register_operand" "r")
3665 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
3666 (ANY_EXTEND:DI
3667 (match_operand:SI 2 "register_operand" "r")))))]
3668 ""
3669 "<su>msubl\\t%0, %w1, %w2, %3"
3670 [(set_attr "type" "<su>mlal")]
3671 )
3672
3673 (define_insn "*<su_optab>mulsidi_neg"
3674 [(set (match_operand:DI 0 "register_operand" "=r")
3675 (mult:DI (neg:DI
3676 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
3677 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
3678 ""
3679 "<su>mnegl\\t%0, %w1, %w2"
3680 [(set_attr "type" "<su>mull")]
3681 )
3682
3683 (define_expand "<su_optab>mulditi3"
3684 [(set (match_operand:TI 0 "register_operand")
3685 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
3686 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
3687 ""
3688 {
3689 rtx low = gen_reg_rtx (DImode);
3690 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
3691
3692 rtx high = gen_reg_rtx (DImode);
3693 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
3694
3695 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
3696 emit_move_insn (gen_highpart (DImode, operands[0]), high);
3697 DONE;
3698 })
3699
3700 ;; The default expansion of multi3 using umuldi3_highpart will perform
3701 ;; the additions in an order that fails to combine into two madd insns.
3702 (define_expand "multi3"
3703 [(set (match_operand:TI 0 "register_operand")
3704 (mult:TI (match_operand:TI 1 "register_operand")
3705 (match_operand:TI 2 "register_operand")))]
3706 ""
3707 {
3708 rtx l0 = gen_reg_rtx (DImode);
3709 rtx l1 = gen_lowpart (DImode, operands[1]);
3710 rtx l2 = gen_lowpart (DImode, operands[2]);
3711 rtx h0 = gen_reg_rtx (DImode);
3712 rtx h1 = gen_highpart (DImode, operands[1]);
3713 rtx h2 = gen_highpart (DImode, operands[2]);
3714
3715 emit_insn (gen_muldi3 (l0, l1, l2));
3716 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3717 emit_insn (gen_madddi (h0, h1, l2, h0));
3718 emit_insn (gen_madddi (h0, l1, h2, h0));
3719
3720 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
3721 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
3722 DONE;
3723 })
3724
3725 (define_insn "<su>muldi3_highpart"
3726 [(set (match_operand:DI 0 "register_operand" "=r")
3727 (truncate:DI
3728 (lshiftrt:TI
3729 (mult:TI
3730 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
3731 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
3732 (const_int 64))))]
3733 ""
3734 "<su>mulh\\t%0, %1, %2"
3735 [(set_attr "type" "<su>mull")]
3736 )
3737
3738 (define_insn "<su_optab>div<mode>3"
3739 [(set (match_operand:GPI 0 "register_operand" "=r")
3740 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
3741 (match_operand:GPI 2 "register_operand" "r")))]
3742 ""
3743 "<su>div\\t%<w>0, %<w>1, %<w>2"
3744 [(set_attr "type" "<su>div")]
3745 )
3746
3747 ;; zero_extend version of above
3748 (define_insn "*<su_optab>divsi3_uxtw"
3749 [(set (match_operand:DI 0 "register_operand" "=r")
3750 (zero_extend:DI
3751 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
3752 (match_operand:SI 2 "register_operand" "r"))))]
3753 ""
3754 "<su>div\\t%w0, %w1, %w2"
3755 [(set_attr "type" "<su>div")]
3756 )
3757
3758 ;; -------------------------------------------------------------------
3759 ;; Comparison insns
3760 ;; -------------------------------------------------------------------
3761
3762 (define_insn "cmp<mode>"
3763 [(set (reg:CC CC_REGNUM)
3764 (compare:CC (match_operand:GPI 0 "register_operand" "rk,rk,rk")
3765 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
3766 ""
3767 "@
3768 cmp\\t%<w>0, %<w>1
3769 cmp\\t%<w>0, %1
3770 cmn\\t%<w>0, #%n1"
3771 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3772 )
3773
3774 (define_insn "fcmp<mode>"
3775 [(set (reg:CCFP CC_REGNUM)
3776 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
3777 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3778 "TARGET_FLOAT"
3779 "@
3780 fcmp\\t%<s>0, #0.0
3781 fcmp\\t%<s>0, %<s>1"
3782 [(set_attr "type" "fcmp<s>")]
3783 )
3784
3785 (define_insn "fcmpe<mode>"
3786 [(set (reg:CCFPE CC_REGNUM)
3787 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
3788 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3789 "TARGET_FLOAT"
3790 "@
3791 fcmpe\\t%<s>0, #0.0
3792 fcmpe\\t%<s>0, %<s>1"
3793 [(set_attr "type" "fcmp<s>")]
3794 )
3795
3796 (define_insn "*cmp_swp_<shift>_reg<mode>"
3797 [(set (reg:CC_SWP CC_REGNUM)
3798 (compare:CC_SWP (ASHIFT:GPI
3799 (match_operand:GPI 0 "register_operand" "r")
3800 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3801 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3802 ""
3803 "cmp\\t%<w>2, %<w>0, <shift> %1"
3804 [(set_attr "type" "alus_shift_imm")]
3805 )
3806
3807 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3808 [(set (reg:CC_SWP CC_REGNUM)
3809 (compare:CC_SWP (ANY_EXTEND:GPI
3810 (match_operand:ALLX 0 "register_operand" "r"))
3811 (match_operand:GPI 1 "register_operand" "r")))]
3812 ""
3813 "cmp\\t%<GPI:w>1, %w0, <su>xt<ALLX:size>"
3814 [(set_attr "type" "alus_ext")]
3815 )
3816
3817 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3818 [(set (reg:CC_SWP CC_REGNUM)
3819 (compare:CC_SWP (ashift:GPI
3820 (ANY_EXTEND:GPI
3821 (match_operand:ALLX 0 "register_operand" "r"))
3822 (match_operand 1 "aarch64_imm3" "Ui3"))
3823 (match_operand:GPI 2 "register_operand" "r")))]
3824 ""
3825 "cmp\\t%<GPI:w>2, %w0, <su>xt<ALLX:size> %1"
3826 [(set_attr "type" "alus_ext")]
3827 )
3828
3829 ;; -------------------------------------------------------------------
3830 ;; Store-flag and conditional select insns
3831 ;; -------------------------------------------------------------------
3832
3833 (define_expand "cstore<mode>4"
3834 [(set (match_operand:SI 0 "register_operand")
3835 (match_operator:SI 1 "aarch64_comparison_operator"
3836 [(match_operand:GPI 2 "register_operand")
3837 (match_operand:GPI 3 "aarch64_plus_operand")]))]
3838 ""
3839 "
3840 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3841 operands[3]);
3842 operands[3] = const0_rtx;
3843 "
3844 )
3845
3846 (define_expand "cstorecc4"
3847 [(set (match_operand:SI 0 "register_operand")
3848 (match_operator 1 "aarch64_comparison_operator_mode"
3849 [(match_operand 2 "cc_register")
3850 (match_operand 3 "const0_operand")]))]
3851 ""
3852 "{
3853 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3854 DONE;
3855 }")
3856
3857
3858 (define_expand "cstore<mode>4"
3859 [(set (match_operand:SI 0 "register_operand")
3860 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3861 [(match_operand:GPF 2 "register_operand")
3862 (match_operand:GPF 3 "aarch64_fp_compare_operand")]))]
3863 ""
3864 "
3865 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3866 operands[3]);
3867 operands[3] = const0_rtx;
3868 "
3869 )
3870
3871 (define_insn "aarch64_cstore<mode>"
3872 [(set (match_operand:ALLI 0 "register_operand" "=r")
3873 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3874 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3875 ""
3876 "cset\\t%<w>0, %m1"
3877 [(set_attr "type" "csel")]
3878 )
3879
3880 ;; For a 24-bit immediate CST we can optimize the compare for equality
3881 ;; and branch sequence from:
3882 ;; mov x0, #imm1
3883 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3884 ;; cmp x1, x0
3885 ;; cset x2, <ne,eq>
3886 ;; into the shorter:
3887 ;; sub x0, x1, #(CST & 0xfff000)
3888 ;; subs x0, x0, #(CST & 0x000fff)
3889 ;; cset x2, <ne, eq>.
3890 (define_insn_and_split "*compare_cstore<mode>_insn"
3891 [(set (match_operand:GPI 0 "register_operand" "=r")
3892 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3893 (match_operand:GPI 2 "aarch64_imm24" "n")))
3894 (clobber (reg:CC CC_REGNUM))]
3895 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3896 && !aarch64_plus_operand (operands[2], <MODE>mode)
3897 && !reload_completed"
3898 "#"
3899 "&& true"
3900 [(const_int 0)]
3901 {
3902 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3903 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3904 rtx tmp = gen_reg_rtx (<MODE>mode);
3905 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3906 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3907 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3908 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3909 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3910 DONE;
3911 }
3912 [(set_attr "type" "csel")]
3913 )
3914
3915 ;; zero_extend version of the above
3916 (define_insn "*cstoresi_insn_uxtw"
3917 [(set (match_operand:DI 0 "register_operand" "=r")
3918 (zero_extend:DI
3919 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3920 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3921 ""
3922 "cset\\t%w0, %m1"
3923 [(set_attr "type" "csel")]
3924 )
3925
3926 (define_insn "cstore<mode>_neg"
3927 [(set (match_operand:ALLI 0 "register_operand" "=r")
3928 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3929 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3930 ""
3931 "csetm\\t%<w>0, %m1"
3932 [(set_attr "type" "csel")]
3933 )
3934
3935 ;; zero_extend version of the above
3936 (define_insn "*cstoresi_neg_uxtw"
3937 [(set (match_operand:DI 0 "register_operand" "=r")
3938 (zero_extend:DI
3939 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3940 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3941 ""
3942 "csetm\\t%w0, %m1"
3943 [(set_attr "type" "csel")]
3944 )
3945
3946 (define_expand "cmov<mode>6"
3947 [(set (match_operand:GPI 0 "register_operand")
3948 (if_then_else:GPI
3949 (match_operator 1 "aarch64_comparison_operator"
3950 [(match_operand:GPI 2 "register_operand")
3951 (match_operand:GPI 3 "aarch64_plus_operand")])
3952 (match_operand:GPI 4 "register_operand")
3953 (match_operand:GPI 5 "register_operand")))]
3954 ""
3955 "
3956 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3957 operands[3]);
3958 operands[3] = const0_rtx;
3959 "
3960 )
3961
3962 (define_expand "cmov<mode>6"
3963 [(set (match_operand:GPF 0 "register_operand")
3964 (if_then_else:GPF
3965 (match_operator 1 "aarch64_comparison_operator"
3966 [(match_operand:GPF 2 "register_operand")
3967 (match_operand:GPF 3 "aarch64_fp_compare_operand")])
3968 (match_operand:GPF 4 "register_operand")
3969 (match_operand:GPF 5 "register_operand")))]
3970 ""
3971 "
3972 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3973 operands[3]);
3974 operands[3] = const0_rtx;
3975 "
3976 )
3977
3978 (define_insn "*cmov<mode>_insn"
3979 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3980 (if_then_else:ALLI
3981 (match_operator 1 "aarch64_comparison_operator"
3982 [(match_operand 2 "cc_register" "") (const_int 0)])
3983 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3984 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3985 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3986 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3987 ;; Final two alternatives should be unreachable, but included for completeness
3988 "@
3989 csel\\t%<w>0, %<w>3, %<w>4, %m1
3990 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3991 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3992 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3993 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3994 mov\\t%<w>0, -1
3995 mov\\t%<w>0, 1"
3996 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3997 )
3998
3999 ;; zero_extend version of above
4000 (define_insn "*cmovsi_insn_uxtw"
4001 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
4002 (zero_extend:DI
4003 (if_then_else:SI
4004 (match_operator 1 "aarch64_comparison_operator"
4005 [(match_operand 2 "cc_register" "") (const_int 0)])
4006 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4007 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
4008 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
4009 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
4010 ;; Final two alternatives should be unreachable, but included for completeness
4011 "@
4012 csel\\t%w0, %w3, %w4, %m1
4013 csinv\\t%w0, %w3, wzr, %m1
4014 csinv\\t%w0, %w4, wzr, %M1
4015 csinc\\t%w0, %w3, wzr, %m1
4016 csinc\\t%w0, %w4, wzr, %M1
4017 mov\\t%w0, -1
4018 mov\\t%w0, 1"
4019 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4020 )
4021
4022 (define_insn "*cmovdi_insn_uxtw"
4023 [(set (match_operand:DI 0 "register_operand" "=r")
4024 (if_then_else:DI
4025 (match_operator 1 "aarch64_comparison_operator"
4026 [(match_operand 2 "cc_register" "") (const_int 0)])
4027 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
4028 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
4029 ""
4030 "csel\\t%w0, %w3, %w4, %m1"
4031 [(set_attr "type" "csel")]
4032 )
4033
4034 (define_insn "*cmov<mode>_insn"
4035 [(set (match_operand:GPF 0 "register_operand" "=w")
4036 (if_then_else:GPF
4037 (match_operator 1 "aarch64_comparison_operator"
4038 [(match_operand 2 "cc_register" "") (const_int 0)])
4039 (match_operand:GPF 3 "register_operand" "w")
4040 (match_operand:GPF 4 "register_operand" "w")))]
4041 "TARGET_FLOAT"
4042 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
4043 [(set_attr "type" "fcsel")]
4044 )
4045
4046 (define_expand "mov<mode>cc"
4047 [(set (match_operand:ALLI 0 "register_operand")
4048 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator")
4049 (match_operand:ALLI 2 "register_operand")
4050 (match_operand:ALLI 3 "register_operand")))]
4051 ""
4052 {
4053 rtx ccreg;
4054 enum rtx_code code = GET_CODE (operands[1]);
4055
4056 if (code == UNEQ || code == LTGT)
4057 FAIL;
4058
4059 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4060 XEXP (operands[1], 1));
4061 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4062 }
4063 )
4064
4065 (define_expand "mov<GPF:mode><GPI:mode>cc"
4066 [(set (match_operand:GPI 0 "register_operand")
4067 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator")
4068 (match_operand:GPF 2 "register_operand")
4069 (match_operand:GPF 3 "register_operand")))]
4070 ""
4071 {
4072 rtx ccreg;
4073 enum rtx_code code = GET_CODE (operands[1]);
4074
4075 if (code == UNEQ || code == LTGT)
4076 FAIL;
4077
4078 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4079 XEXP (operands[1], 1));
4080 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4081 }
4082 )
4083
4084 (define_expand "mov<mode>cc"
4085 [(set (match_operand:GPF 0 "register_operand")
4086 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator")
4087 (match_operand:GPF 2 "register_operand")
4088 (match_operand:GPF 3 "register_operand")))]
4089 ""
4090 {
4091 rtx ccreg;
4092 enum rtx_code code = GET_CODE (operands[1]);
4093
4094 if (code == UNEQ || code == LTGT)
4095 FAIL;
4096
4097 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4098 XEXP (operands[1], 1));
4099 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4100 }
4101 )
4102
4103 (define_expand "<neg_not_op><mode>cc"
4104 [(set (match_operand:GPI 0 "register_operand")
4105 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator")
4106 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand"))
4107 (match_operand:GPI 3 "register_operand")))]
4108 ""
4109 {
4110 rtx ccreg;
4111 enum rtx_code code = GET_CODE (operands[1]);
4112
4113 if (code == UNEQ || code == LTGT)
4114 FAIL;
4115
4116 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4117 XEXP (operands[1], 1));
4118 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4119 }
4120 )
4121
4122 ;; CRC32 instructions.
4123 (define_insn "aarch64_<crc_variant>"
4124 [(set (match_operand:SI 0 "register_operand" "=r")
4125 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
4126 (match_operand:<crc_mode> 2 "register_operand" "r")]
4127 CRC))]
4128 "TARGET_CRC32"
4129 {
4130 if (GET_MODE_BITSIZE (<crc_mode>mode) >= 64)
4131 return "<crc_variant>\\t%w0, %w1, %x2";
4132 else
4133 return "<crc_variant>\\t%w0, %w1, %w2";
4134 }
4135 [(set_attr "type" "crc")]
4136 )
4137
4138 (define_insn "*csinc2<mode>_insn"
4139 [(set (match_operand:GPI 0 "register_operand" "=r")
4140 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
4141 (match_operand:GPI 1 "register_operand" "r")))]
4142 ""
4143 "cinc\\t%<w>0, %<w>1, %m2"
4144 [(set_attr "type" "csel")]
4145 )
4146
4147 (define_insn "csinc3<mode>_insn"
4148 [(set (match_operand:GPI 0 "register_operand" "=r")
4149 (if_then_else:GPI
4150 (match_operand 1 "aarch64_comparison_operation" "")
4151 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
4152 (const_int 1))
4153 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4154 ""
4155 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
4156 [(set_attr "type" "csel")]
4157 )
4158
4159 (define_insn "*csinv3<mode>_insn"
4160 [(set (match_operand:GPI 0 "register_operand" "=r")
4161 (if_then_else:GPI
4162 (match_operand 1 "aarch64_comparison_operation" "")
4163 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
4164 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4165 ""
4166 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
4167 [(set_attr "type" "csel")]
4168 )
4169
4170 (define_insn "csneg3_uxtw_insn"
4171 [(set (match_operand:DI 0 "register_operand" "=r")
4172 (zero_extend:DI
4173 (if_then_else:SI
4174 (match_operand 1 "aarch64_comparison_operation" "")
4175 (neg:SI (match_operand:SI 2 "register_operand" "r"))
4176 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
4177 ""
4178 "csneg\\t%w0, %w3, %w2, %M1"
4179 [(set_attr "type" "csel")]
4180 )
4181
4182 (define_insn "csneg3<mode>_insn"
4183 [(set (match_operand:GPI 0 "register_operand" "=r")
4184 (if_then_else:GPI
4185 (match_operand 1 "aarch64_comparison_operation" "")
4186 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
4187 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4188 ""
4189 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
4190 [(set_attr "type" "csel")]
4191 )
4192
4193 (define_insn "*csinv3_uxtw_insn1"
4194 [(set (match_operand:DI 0 "register_operand" "=r")
4195 (if_then_else:DI
4196 (match_operand 1 "aarch64_comparison_operation" "")
4197 (zero_extend:DI
4198 (match_operand:SI 2 "register_operand" "r"))
4199 (zero_extend:DI
4200 (NEG_NOT:SI (match_operand:SI 3 "register_operand" "r")))))]
4201 ""
4202 "cs<neg_not_cs>\\t%w0, %w2, %w3, %m1"
4203 [(set_attr "type" "csel")]
4204 )
4205
4206 (define_insn "*csinv3_uxtw_insn2"
4207 [(set (match_operand:DI 0 "register_operand" "=r")
4208 (if_then_else:DI
4209 (match_operand 1 "aarch64_comparison_operation" "")
4210 (zero_extend:DI
4211 (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
4212 (zero_extend:DI
4213 (match_operand:SI 3 "register_operand" "r"))))]
4214 ""
4215 "cs<neg_not_cs>\\t%w0, %w3, %w2, %M1"
4216 [(set_attr "type" "csel")]
4217 )
4218
4219 (define_insn "*csinv3_uxtw_insn3"
4220 [(set (match_operand:DI 0 "register_operand" "=r")
4221 (if_then_else:DI
4222 (match_operand 1 "aarch64_comparison_operation" "")
4223 (zero_extend:DI
4224 (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
4225 (const_int 0)))]
4226 ""
4227 "cs<neg_not_cs>\\t%w0, wzr, %w2, %M1"
4228 [(set_attr "type" "csel")]
4229 )
4230
4231 ;; If X can be loaded by a single CNT[BHWD] instruction,
4232 ;;
4233 ;; A = UMAX (B, X)
4234 ;;
4235 ;; is equivalent to:
4236 ;;
4237 ;; TMP = UQDEC[BHWD] (B, X)
4238 ;; A = TMP + X
4239 ;;
4240 ;; Defining the pattern this way means that:
4241 ;;
4242 ;; A = UMAX (B, X) - X
4243 ;;
4244 ;; becomes:
4245 ;;
4246 ;; TMP1 = UQDEC[BHWD] (B, X)
4247 ;; TMP2 = TMP1 + X
4248 ;; A = TMP2 - X
4249 ;;
4250 ;; which combine can optimize to:
4251 ;;
4252 ;; A = UQDEC[BHWD] (B, X)
4253 ;;
4254 ;; We don't use match_operand predicates because the order of the operands
4255 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
4256 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
4257 (define_expand "umax<mode>3"
4258 [(set (match_operand:GPI 0 "register_operand")
4259 (umax:GPI (match_operand:GPI 1 "")
4260 (match_operand:GPI 2 "")))]
4261 "TARGET_SVE"
4262 {
4263 if (aarch64_sve_cnt_immediate (operands[1], <MODE>mode))
4264 std::swap (operands[1], operands[2]);
4265 else if (!aarch64_sve_cnt_immediate (operands[2], <MODE>mode))
4266 FAIL;
4267 rtx temp = gen_reg_rtx (<MODE>mode);
4268 operands[1] = force_reg (<MODE>mode, operands[1]);
4269 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[1], operands[2]));
4270 emit_insn (gen_add<mode>3 (operands[0], temp, operands[2]));
4271 DONE;
4272 }
4273 )
4274
4275 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4276 (define_insn "aarch64_uqdec<mode>"
4277 [(set (match_operand:GPI 0 "register_operand" "=r")
4278 (minus:GPI
4279 (umax:GPI (match_operand:GPI 1 "register_operand" "0")
4280 (match_operand:GPI 2 "aarch64_sve_cnt_immediate" "Usv"))
4281 (match_dup 2)))]
4282 "TARGET_SVE"
4283 {
4284 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>0", operands[2]);
4285 }
4286 )
4287
4288 ;; -------------------------------------------------------------------
4289 ;; Logical operations
4290 ;; -------------------------------------------------------------------
4291
4292
4293 (define_insn_and_split "*aarch64_and<mode>_imm2"
4294 [(set (match_operand:GPI 0 "register_operand" "=rk")
4295 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
4296 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
4297 ""
4298 "#"
4299 "true"
4300 [(const_int 0)]
4301 {
4302 HOST_WIDE_INT val = INTVAL (operands[2]);
4303 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
4304 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
4305
4306 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
4307 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
4308 DONE;
4309 }
4310 )
4311
4312 (define_insn "<optab><mode>3"
4313 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
4314 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
4315 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
4316 ""
4317 "@
4318 <logical>\\t%<w>0, %<w>1, %<w>2
4319 <logical>\\t%<w>0, %<w>1, %2
4320 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
4321 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
4322 (set_attr "arch" "*,*,simd")]
4323 )
4324
4325 ;; zero_extend version of above
4326 (define_insn "*<optab>si3_uxtw"
4327 [(set (match_operand:DI 0 "register_operand" "=r,rk")
4328 (zero_extend:DI
4329 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
4330 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
4331 ""
4332 "@
4333 <logical>\\t%w0, %w1, %w2
4334 <logical>\\t%w0, %w1, %2"
4335 [(set_attr "type" "logic_reg,logic_imm")]
4336 )
4337
4338 (define_insn "*and<mode>3_compare0"
4339 [(set (reg:CC_NZ CC_REGNUM)
4340 (compare:CC_NZ
4341 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
4342 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
4343 (const_int 0)))
4344 (set (match_operand:GPI 0 "register_operand" "=r,r")
4345 (and:GPI (match_dup 1) (match_dup 2)))]
4346 ""
4347 "@
4348 ands\\t%<w>0, %<w>1, %<w>2
4349 ands\\t%<w>0, %<w>1, %2"
4350 [(set_attr "type" "logics_reg,logics_imm")]
4351 )
4352
4353 ;; zero_extend version of above
4354 (define_insn "*andsi3_compare0_uxtw"
4355 [(set (reg:CC_NZ CC_REGNUM)
4356 (compare:CC_NZ
4357 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
4358 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
4359 (const_int 0)))
4360 (set (match_operand:DI 0 "register_operand" "=r,r")
4361 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
4362 ""
4363 "@
4364 ands\\t%w0, %w1, %w2
4365 ands\\t%w0, %w1, %2"
4366 [(set_attr "type" "logics_reg,logics_imm")]
4367 )
4368
4369 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
4370 [(set (reg:CC_NZ CC_REGNUM)
4371 (compare:CC_NZ
4372 (and:GPI (SHIFT:GPI
4373 (match_operand:GPI 1 "register_operand" "r")
4374 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4375 (match_operand:GPI 3 "register_operand" "r"))
4376 (const_int 0)))
4377 (set (match_operand:GPI 0 "register_operand" "=r")
4378 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
4379 ""
4380 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4381 [(set_attr "type" "logics_shift_imm")]
4382 )
4383
4384 ;; zero_extend version of above
4385 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
4386 [(set (reg:CC_NZ CC_REGNUM)
4387 (compare:CC_NZ
4388 (and:SI (SHIFT:SI
4389 (match_operand:SI 1 "register_operand" "r")
4390 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4391 (match_operand:SI 3 "register_operand" "r"))
4392 (const_int 0)))
4393 (set (match_operand:DI 0 "register_operand" "=r")
4394 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
4395 (match_dup 3))))]
4396 ""
4397 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4398 [(set_attr "type" "logics_shift_imm")]
4399 )
4400
4401 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
4402 [(set (match_operand:GPI 0 "register_operand" "=r")
4403 (LOGICAL:GPI (SHIFT:GPI
4404 (match_operand:GPI 1 "register_operand" "r")
4405 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4406 (match_operand:GPI 3 "register_operand" "r")))]
4407 ""
4408 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4409 [(set_attr "type" "logic_shift_imm")]
4410 )
4411
4412 (define_insn "*<optab>_rol<mode>3"
4413 [(set (match_operand:GPI 0 "register_operand" "=r")
4414 (LOGICAL:GPI (rotate:GPI
4415 (match_operand:GPI 1 "register_operand" "r")
4416 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4417 (match_operand:GPI 3 "register_operand" "r")))]
4418 ""
4419 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
4420 [(set_attr "type" "logic_shift_imm")]
4421 )
4422
4423 ;; zero_extend versions of above
4424 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
4425 [(set (match_operand:DI 0 "register_operand" "=r")
4426 (zero_extend:DI
4427 (LOGICAL:SI (SHIFT:SI
4428 (match_operand:SI 1 "register_operand" "r")
4429 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4430 (match_operand:SI 3 "register_operand" "r"))))]
4431 ""
4432 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4433 [(set_attr "type" "logic_shift_imm")]
4434 )
4435
4436 (define_insn "*<optab>_rolsi3_uxtw"
4437 [(set (match_operand:DI 0 "register_operand" "=r")
4438 (zero_extend:DI
4439 (LOGICAL:SI (rotate:SI
4440 (match_operand:SI 1 "register_operand" "r")
4441 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4442 (match_operand:SI 3 "register_operand" "r"))))]
4443 ""
4444 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
4445 [(set_attr "type" "logic_shift_imm")]
4446 )
4447
4448 (define_insn "one_cmpl<mode>2"
4449 [(set (match_operand:GPI 0 "register_operand" "=r,w")
4450 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
4451 ""
4452 "@
4453 mvn\\t%<w>0, %<w>1
4454 mvn\\t%0.8b, %1.8b"
4455 [(set_attr "type" "logic_reg,neon_logic")
4456 (set_attr "arch" "*,simd")]
4457 )
4458
4459 (define_insn "*one_cmpl_zero_extend"
4460 [(set (match_operand:DI 0 "register_operand" "=r")
4461 (zero_extend:DI
4462 (not:SI (match_operand:SI 1 "register_operand" "r"))))]
4463 ""
4464 "mvn\\t%w0, %w1"
4465 [(set_attr "type" "logic_reg")]
4466 )
4467
4468 (define_insn "*one_cmpl_<optab><mode>2"
4469 [(set (match_operand:GPI 0 "register_operand" "=r")
4470 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
4471 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
4472 ""
4473 "mvn\\t%<w>0, %<w>1, <shift> %2"
4474 [(set_attr "type" "logic_shift_imm")]
4475 )
4476
4477 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
4478
4479 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
4480 [(set (match_operand:GPI 0 "register_operand" "=r,w")
4481 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
4482 (match_operand:GPI 2 "register_operand" "r,w")))]
4483 ""
4484 "@
4485 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
4486 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
4487 [(set_attr "type" "logic_reg,neon_logic")
4488 (set_attr "arch" "*,simd")]
4489 )
4490
4491 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
4492 [(set (match_operand:DI 0 "register_operand" "=r")
4493 (zero_extend:DI
4494 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
4495 (match_operand:SI 2 "register_operand" "r"))))]
4496 ""
4497 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
4498 [(set_attr "type" "logic_reg")]
4499 )
4500
4501 (define_insn "*xor_one_cmplsidi3_ze"
4502 [(set (match_operand:DI 0 "register_operand" "=r")
4503 (zero_extend:DI
4504 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
4505 (match_operand:SI 2 "register_operand" "r")))))]
4506 ""
4507 "eon\\t%w0, %w1, %w2"
4508 [(set_attr "type" "logic_reg")]
4509 )
4510
4511 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
4512 ;; eon does not operate on SIMD registers so the vector variant must be split.
4513 (define_insn_and_split "*xor_one_cmpl<mode>3"
4514 [(set (match_operand:GPI 0 "register_operand" "=r,w")
4515 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
4516 (match_operand:GPI 2 "register_operand" "r,w"))))]
4517 ""
4518 "@
4519 eon\\t%<w>0, %<w>1, %<w>2
4520 #"
4521 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
4522 [(set (match_operand:GPI 0 "register_operand" "=w")
4523 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
4524 (match_operand:GPI 2 "register_operand" "w")))
4525 (set (match_dup 0) (not:GPI (match_dup 0)))]
4526 ""
4527 [(set_attr "type" "logic_reg,multiple")
4528 (set_attr "arch" "*,simd")]
4529 )
4530
4531 (define_insn "*and_one_cmpl<mode>3_compare0"
4532 [(set (reg:CC_NZ CC_REGNUM)
4533 (compare:CC_NZ
4534 (and:GPI (not:GPI
4535 (match_operand:GPI 1 "register_operand" "r"))
4536 (match_operand:GPI 2 "register_operand" "r"))
4537 (const_int 0)))
4538 (set (match_operand:GPI 0 "register_operand" "=r")
4539 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
4540 ""
4541 "bics\\t%<w>0, %<w>2, %<w>1"
4542 [(set_attr "type" "logics_reg")]
4543 )
4544
4545 ;; zero_extend version of above
4546 (define_insn "*and_one_cmplsi3_compare0_uxtw"
4547 [(set (reg:CC_NZ CC_REGNUM)
4548 (compare:CC_NZ
4549 (and:SI (not:SI
4550 (match_operand:SI 1 "register_operand" "r"))
4551 (match_operand:SI 2 "register_operand" "r"))
4552 (const_int 0)))
4553 (set (match_operand:DI 0 "register_operand" "=r")
4554 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
4555 ""
4556 "bics\\t%w0, %w2, %w1"
4557 [(set_attr "type" "logics_reg")]
4558 )
4559
4560 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
4561 [(set (reg:CC_NZ CC_REGNUM)
4562 (compare:CC_NZ
4563 (and:GPI (not:GPI
4564 (match_operand:GPI 0 "register_operand" "r"))
4565 (match_operand:GPI 1 "register_operand" "r"))
4566 (const_int 0)))]
4567 ""
4568 "bics\\t<w>zr, %<w>1, %<w>0"
4569 [(set_attr "type" "logics_reg")]
4570 )
4571
4572 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
4573 [(set (match_operand:GPI 0 "register_operand" "=r")
4574 (LOGICAL:GPI (not:GPI
4575 (SHIFT:GPI
4576 (match_operand:GPI 1 "register_operand" "r")
4577 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
4578 (match_operand:GPI 3 "register_operand" "r")))]
4579 ""
4580 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4581 [(set_attr "type" "logic_shift_imm")]
4582 )
4583
4584 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
4585 [(set (match_operand:GPI 0 "register_operand" "=r")
4586 (not:GPI (xor:GPI
4587 (SHIFT:GPI
4588 (match_operand:GPI 1 "register_operand" "r")
4589 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4590 (match_operand:GPI 3 "register_operand" "r"))))]
4591 ""
4592 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4593 [(set_attr "type" "logic_shift_imm")]
4594 )
4595
4596 ;; Zero-extend version of the above.
4597 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
4598 [(set (match_operand:DI 0 "register_operand" "=r")
4599 (zero_extend:DI
4600 (not:SI (xor:SI
4601 (SHIFT:SI
4602 (match_operand:SI 1 "register_operand" "r")
4603 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4604 (match_operand:SI 3 "register_operand" "r")))))]
4605 ""
4606 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4607 [(set_attr "type" "logic_shift_imm")]
4608 )
4609
4610 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
4611 [(set (reg:CC_NZ CC_REGNUM)
4612 (compare:CC_NZ
4613 (and:GPI (not:GPI
4614 (SHIFT:GPI
4615 (match_operand:GPI 1 "register_operand" "r")
4616 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
4617 (match_operand:GPI 3 "register_operand" "r"))
4618 (const_int 0)))
4619 (set (match_operand:GPI 0 "register_operand" "=r")
4620 (and:GPI (not:GPI
4621 (SHIFT:GPI
4622 (match_dup 1) (match_dup 2))) (match_dup 3)))]
4623 ""
4624 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4625 [(set_attr "type" "logics_shift_imm")]
4626 )
4627
4628 ;; zero_extend version of above
4629 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
4630 [(set (reg:CC_NZ CC_REGNUM)
4631 (compare:CC_NZ
4632 (and:SI (not:SI
4633 (SHIFT:SI
4634 (match_operand:SI 1 "register_operand" "r")
4635 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
4636 (match_operand:SI 3 "register_operand" "r"))
4637 (const_int 0)))
4638 (set (match_operand:DI 0 "register_operand" "=r")
4639 (zero_extend:DI (and:SI
4640 (not:SI
4641 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
4642 ""
4643 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4644 [(set_attr "type" "logics_shift_imm")]
4645 )
4646
4647 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
4648 [(set (reg:CC_NZ CC_REGNUM)
4649 (compare:CC_NZ
4650 (and:GPI (not:GPI
4651 (SHIFT:GPI
4652 (match_operand:GPI 0 "register_operand" "r")
4653 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
4654 (match_operand:GPI 2 "register_operand" "r"))
4655 (const_int 0)))]
4656 ""
4657 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
4658 [(set_attr "type" "logics_shift_imm")]
4659 )
4660
4661 (define_insn "clz<mode>2"
4662 [(set (match_operand:GPI 0 "register_operand" "=r")
4663 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
4664 ""
4665 "clz\\t%<w>0, %<w>1"
4666 [(set_attr "type" "clz")]
4667 )
4668
4669 (define_expand "ffs<mode>2"
4670 [(match_operand:GPI 0 "register_operand")
4671 (match_operand:GPI 1 "register_operand")]
4672 ""
4673 {
4674 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
4675 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
4676
4677 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
4678 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
4679 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
4680 DONE;
4681 }
4682 )
4683
4684 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
4685 ;;
4686 ;; MOV v.1d, x0
4687 ;; CNT v1.8b, v.8b
4688 ;; ADDV b2, v1.8b
4689 ;; MOV w0, v2.b[0]
4690
4691 (define_expand "popcount<mode>2"
4692 [(match_operand:GPI 0 "register_operand")
4693 (match_operand:GPI 1 "register_operand")]
4694 "TARGET_SIMD"
4695 {
4696 rtx v = gen_reg_rtx (V8QImode);
4697 rtx v1 = gen_reg_rtx (V8QImode);
4698 rtx in = operands[1];
4699 rtx out = operands[0];
4700 if(<MODE>mode == SImode)
4701 {
4702 rtx tmp;
4703 tmp = gen_reg_rtx (DImode);
4704 /* If we have SImode, zero extend to DImode, pop count does
4705 not change if we have extra zeros. */
4706 emit_insn (gen_zero_extendsidi2 (tmp, in));
4707 in = tmp;
4708 }
4709 emit_move_insn (v, gen_lowpart (V8QImode, in));
4710 emit_insn (gen_popcountv8qi2 (v1, v));
4711 emit_insn (gen_aarch64_zero_extend<mode>_reduc_plus_v8qi (out, v1));
4712 DONE;
4713 })
4714
4715 (define_insn "clrsb<mode>2"
4716 [(set (match_operand:GPI 0 "register_operand" "=r")
4717 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
4718 ""
4719 "cls\\t%<w>0, %<w>1"
4720 [(set_attr "type" "clz")]
4721 )
4722
4723 (define_insn "rbit<mode>2"
4724 [(set (match_operand:GPI 0 "register_operand" "=r")
4725 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
4726 ""
4727 "rbit\\t%<w>0, %<w>1"
4728 [(set_attr "type" "rbit")]
4729 )
4730
4731 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
4732 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
4733 ;; expression and split after reload to enable scheduling them apart if
4734 ;; needed.
4735
4736 (define_insn_and_split "ctz<mode>2"
4737 [(set (match_operand:GPI 0 "register_operand" "=r")
4738 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
4739 ""
4740 "#"
4741 "reload_completed"
4742 [(const_int 0)]
4743 "
4744 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
4745 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
4746 DONE;
4747 ")
4748
4749 (define_insn "*and<mode>_compare0"
4750 [(set (reg:CC_NZ CC_REGNUM)
4751 (compare:CC_NZ
4752 (match_operand:SHORT 0 "register_operand" "r")
4753 (const_int 0)))]
4754 ""
4755 "tst\\t%<w>0, <short_mask>"
4756 [(set_attr "type" "alus_imm")]
4757 )
4758
4759 (define_insn "*ands<GPI:mode>_compare0"
4760 [(set (reg:CC_NZ CC_REGNUM)
4761 (compare:CC_NZ
4762 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
4763 (const_int 0)))
4764 (set (match_operand:GPI 0 "register_operand" "=r")
4765 (zero_extend:GPI (match_dup 1)))]
4766 ""
4767 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
4768 [(set_attr "type" "alus_imm")]
4769 )
4770
4771 (define_insn "*and<mode>3nr_compare0"
4772 [(set (reg:CC_NZ CC_REGNUM)
4773 (compare:CC_NZ
4774 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
4775 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
4776 (const_int 0)))]
4777 ""
4778 "@
4779 tst\\t%<w>0, %<w>1
4780 tst\\t%<w>0, %1"
4781 [(set_attr "type" "logics_reg,logics_imm")]
4782 )
4783
4784 (define_split
4785 [(set (reg:CC_NZ CC_REGNUM)
4786 (compare:CC_NZ
4787 (and:GPI (match_operand:GPI 0 "register_operand")
4788 (match_operand:GPI 1 "aarch64_mov_imm_operand"))
4789 (const_int 0)))
4790 (clobber (match_operand:SI 2 "register_operand"))]
4791 ""
4792 [(set (match_dup 2) (match_dup 1))
4793 (set (reg:CC_NZ CC_REGNUM)
4794 (compare:CC_NZ
4795 (and:GPI (match_dup 0)
4796 (match_dup 2))
4797 (const_int 0)))]
4798 )
4799
4800 (define_insn "*and<mode>3nr_compare0_zextract"
4801 [(set (reg:CC_NZ CC_REGNUM)
4802 (compare:CC_NZ
4803 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
4804 (match_operand:GPI 1 "const_int_operand" "n")
4805 (match_operand:GPI 2 "const_int_operand" "n"))
4806 (const_int 0)))]
4807 "INTVAL (operands[1]) > 0
4808 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
4809 <= GET_MODE_BITSIZE (<MODE>mode))
4810 && aarch64_bitmask_imm (
4811 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
4812 operands[2])),
4813 <MODE>mode)"
4814 {
4815 operands[1]
4816 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
4817 return "tst\\t%<w>0, %1";
4818 }
4819 [(set_attr "type" "logics_shift_imm")]
4820 )
4821
4822 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
4823 [(set (reg:CC_NZ CC_REGNUM)
4824 (compare:CC_NZ
4825 (and:GPI (SHIFT:GPI
4826 (match_operand:GPI 0 "register_operand" "r")
4827 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
4828 (match_operand:GPI 2 "register_operand" "r"))
4829 (const_int 0)))]
4830 ""
4831 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
4832 [(set_attr "type" "logics_shift_imm")]
4833 )
4834
4835 (define_split
4836 [(set (reg:CC_NZ CC_REGNUM)
4837 (compare:CC_NZ
4838 (and:GPI (SHIFT:GPI
4839 (match_operand:GPI 0 "register_operand")
4840 (match_operand:QI 1 "aarch64_shift_imm_<mode>"))
4841 (match_operand:GPI 2 "aarch64_mov_imm_operand"))
4842 (const_int 0)))
4843 (clobber (match_operand:SI 3 "register_operand"))]
4844 ""
4845 [(set (match_dup 3) (match_dup 2))
4846 (set (reg:CC_NZ CC_REGNUM)
4847 (compare:CC_NZ
4848 (and:GPI (SHIFT:GPI
4849 (match_dup 0)
4850 (match_dup 1))
4851 (match_dup 3))
4852 (const_int 0)))]
4853 )
4854
4855 ;; -------------------------------------------------------------------
4856 ;; Shifts
4857 ;; -------------------------------------------------------------------
4858
4859 (define_expand "<optab><mode>3"
4860 [(set (match_operand:GPI 0 "register_operand")
4861 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
4862 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4863 ""
4864 {
4865 if (CONST_INT_P (operands[2]))
4866 {
4867 operands[2] = GEN_INT (INTVAL (operands[2])
4868 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4869
4870 if (operands[2] == const0_rtx)
4871 {
4872 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4873 DONE;
4874 }
4875 }
4876 }
4877 )
4878
4879 (define_expand "ashl<mode>3"
4880 [(set (match_operand:SHORT 0 "register_operand")
4881 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
4882 (match_operand:QI 2 "const_int_operand")))]
4883 ""
4884 {
4885 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
4886
4887 if (operands[2] == const0_rtx)
4888 {
4889 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4890 DONE;
4891 }
4892 }
4893 )
4894
4895 (define_expand "rotr<mode>3"
4896 [(set (match_operand:GPI 0 "register_operand")
4897 (rotatert:GPI (match_operand:GPI 1 "register_operand")
4898 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4899 ""
4900 {
4901 if (CONST_INT_P (operands[2]))
4902 {
4903 operands[2] = GEN_INT (INTVAL (operands[2])
4904 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4905
4906 if (operands[2] == const0_rtx)
4907 {
4908 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4909 DONE;
4910 }
4911 }
4912 }
4913 )
4914
4915 (define_expand "rotl<mode>3"
4916 [(set (match_operand:GPI 0 "register_operand")
4917 (rotatert:GPI (match_operand:GPI 1 "register_operand")
4918 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4919 ""
4920 {
4921 /* (SZ - cnt) % SZ == -cnt % SZ */
4922 if (CONST_INT_P (operands[2]))
4923 {
4924 operands[2] = GEN_INT ((-INTVAL (operands[2]))
4925 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4926 if (operands[2] == const0_rtx)
4927 {
4928 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4929 DONE;
4930 }
4931 }
4932 else
4933 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
4934 NULL_RTX, 1);
4935 }
4936 )
4937
4938 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4939 ;; they truncate the shift/rotate amount by the size of the registers they
4940 ;; operate on: 32 for W-regs, 64 for X-regs. This allows us to optimise away
4941 ;; such redundant masking instructions. GCC can do that automatically when
4942 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4943 ;; because some of the SISD shift alternatives don't perform this truncations.
4944 ;; So this pattern exists to catch such cases.
4945
4946 (define_insn "*aarch64_<optab>_reg_<mode>3_mask1"
4947 [(set (match_operand:GPI 0 "register_operand" "=r")
4948 (SHIFT:GPI
4949 (match_operand:GPI 1 "register_operand" "r")
4950 (match_operator 4 "subreg_lowpart_operator"
4951 [(and:GPI (match_operand:GPI 2 "register_operand" "r")
4952 (match_operand 3 "const_int_operand" "n"))])))]
4953 "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
4954 "<shift>\t%<w>0, %<w>1, %<w>2"
4955 [(set_attr "type" "shift_reg")]
4956 )
4957
4958 (define_insn_and_split "*aarch64_<optab>_reg_<mode>3_neg_mask2"
4959 [(set (match_operand:GPI 0 "register_operand" "=&r")
4960 (SHIFT:GPI
4961 (match_operand:GPI 1 "register_operand" "r")
4962 (match_operator 4 "subreg_lowpart_operator"
4963 [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r")
4964 (match_operand 3 "const_int_operand" "n")))])))]
4965 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)"
4966 "#"
4967 "&& true"
4968 [(const_int 0)]
4969 {
4970 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4971 : lowpart_subreg (SImode, operands[0], <MODE>mode));
4972 emit_insn (gen_negsi2 (tmp, operands[2]));
4973
4974 rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]);
4975 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op,
4976 SUBREG_BYTE (operands[4]));
4977 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp));
4978 DONE;
4979 }
4980 )
4981
4982 (define_insn_and_split "*aarch64_ashl_reg_<mode>3_minus_mask"
4983 [(set (match_operand:GPI 0 "register_operand" "=&r")
4984 (ashift:GPI
4985 (match_operand:GPI 1 "register_operand" "r")
4986 (minus:QI (match_operand 2 "const_int_operand" "n")
4987 (match_operator 5 "subreg_lowpart_operator"
4988 [(and:SI (match_operand:SI 3 "register_operand" "r")
4989 (match_operand 4 "const_int_operand" "n"))]))))]
4990 "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)
4991 && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
4992 "#"
4993 "&& true"
4994 [(const_int 0)]
4995 {
4996 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4997 : operands[0]);
4998
4999 emit_insn (gen_negsi2 (tmp, operands[3]));
5000
5001 rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]);
5002 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op,
5003 SUBREG_BYTE (operands[5]));
5004
5005 emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp));
5006 DONE;
5007 }
5008 )
5009
5010 (define_insn "*aarch64_<optab>_reg_di3_mask2"
5011 [(set (match_operand:DI 0 "register_operand" "=r")
5012 (SHIFT:DI
5013 (match_operand:DI 1 "register_operand" "r")
5014 (match_operator 4 "subreg_lowpart_operator"
5015 [(and:SI (match_operand:SI 2 "register_operand" "r")
5016 (match_operand 3 "const_int_operand" "n"))])))]
5017 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)"
5018 {
5019 rtx xop[3];
5020 xop[0] = operands[0];
5021 xop[1] = operands[1];
5022 xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]);
5023 output_asm_insn ("<shift>\t%x0, %x1, %x2", xop);
5024 return "";
5025 }
5026 [(set_attr "type" "shift_reg")]
5027 )
5028
5029 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>3"
5030 [(set (match_operand:GPI 0 "register_operand" "=&r")
5031 (ASHIFT:GPI
5032 (match_operand:GPI 1 "register_operand" "r")
5033 (minus:QI (match_operand 2 "const_int_operand" "n")
5034 (match_operand:QI 3 "register_operand" "r"))))]
5035 "INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
5036 "#"
5037 "&& true"
5038 [(const_int 0)]
5039 {
5040 rtx subreg_tmp = gen_lowpart (SImode, operands[3]);
5041
5042 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5043 : gen_lowpart (SImode, operands[0]));
5044
5045 emit_insn (gen_negsi2 (tmp, subreg_tmp));
5046
5047 rtx and_op = gen_rtx_AND (SImode, tmp,
5048 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1));
5049
5050 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
5051
5052 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp2));
5053 DONE;
5054 }
5055 [(set_attr "length" "8")]
5056 )
5057
5058 ;; Logical left shift using SISD or Integer instruction
5059 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
5060 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
5061 (ashift:GPI
5062 (match_operand:GPI 1 "register_operand" "r,r,w,w")
5063 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
5064 ""
5065 "@
5066 lsl\t%<w>0, %<w>1, %2
5067 lsl\t%<w>0, %<w>1, %<w>2
5068 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5069 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
5070 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")
5071 (set_attr "arch" "*,*,simd,simd")]
5072 )
5073
5074 ;; Logical right shift using SISD or Integer instruction
5075 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
5076 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
5077 (lshiftrt:GPI
5078 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
5079 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>"
5080 "Us<cmode>,r,Us<cmode_simd>,w,0")))]
5081 ""
5082 "@
5083 lsr\t%<w>0, %<w>1, %2
5084 lsr\t%<w>0, %<w>1, %<w>2
5085 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5086 #
5087 #"
5088 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5089 (set_attr "arch" "*,*,simd,simd,simd")]
5090 )
5091
5092 (define_split
5093 [(set (match_operand:DI 0 "aarch64_simd_register")
5094 (lshiftrt:DI
5095 (match_operand:DI 1 "aarch64_simd_register")
5096 (match_operand:QI 2 "aarch64_simd_register")))]
5097 "TARGET_SIMD && reload_completed"
5098 [(set (match_dup 3)
5099 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5100 (set (match_dup 0)
5101 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
5102 {
5103 operands[3] = gen_lowpart (QImode, operands[0]);
5104 }
5105 )
5106
5107 (define_split
5108 [(set (match_operand:SI 0 "aarch64_simd_register")
5109 (lshiftrt:SI
5110 (match_operand:SI 1 "aarch64_simd_register")
5111 (match_operand:QI 2 "aarch64_simd_register")))]
5112 "TARGET_SIMD && reload_completed"
5113 [(set (match_dup 3)
5114 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5115 (set (match_dup 0)
5116 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
5117 {
5118 operands[3] = gen_lowpart (QImode, operands[0]);
5119 }
5120 )
5121
5122 ;; Arithmetic right shift using SISD or Integer instruction
5123 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
5124 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
5125 (ashiftrt:GPI
5126 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
5127 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di"
5128 "Us<cmode>,r,Us<cmode_simd>,w,0")))]
5129 ""
5130 "@
5131 asr\t%<w>0, %<w>1, %2
5132 asr\t%<w>0, %<w>1, %<w>2
5133 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5134 #
5135 #"
5136 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5137 (set_attr "arch" "*,*,simd,simd,simd")]
5138 )
5139
5140 (define_split
5141 [(set (match_operand:DI 0 "aarch64_simd_register")
5142 (ashiftrt:DI
5143 (match_operand:DI 1 "aarch64_simd_register")
5144 (match_operand:QI 2 "aarch64_simd_register")))]
5145 "TARGET_SIMD && reload_completed"
5146 [(set (match_dup 3)
5147 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5148 (set (match_dup 0)
5149 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
5150 {
5151 operands[3] = gen_lowpart (QImode, operands[0]);
5152 }
5153 )
5154
5155 (define_split
5156 [(set (match_operand:SI 0 "aarch64_simd_register")
5157 (ashiftrt:SI
5158 (match_operand:SI 1 "aarch64_simd_register")
5159 (match_operand:QI 2 "aarch64_simd_register")))]
5160 "TARGET_SIMD && reload_completed"
5161 [(set (match_dup 3)
5162 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5163 (set (match_dup 0)
5164 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
5165 {
5166 operands[3] = gen_lowpart (QImode, operands[0]);
5167 }
5168 )
5169
5170 (define_insn "*aarch64_sisd_ushl"
5171 [(set (match_operand:DI 0 "register_operand" "=w")
5172 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
5173 (match_operand:QI 2 "register_operand" "w")]
5174 UNSPEC_SISD_USHL))]
5175 "TARGET_SIMD"
5176 "ushl\t%d0, %d1, %d2"
5177 [(set_attr "type" "neon_shift_reg")]
5178 )
5179
5180 (define_insn "*aarch64_ushl_2s"
5181 [(set (match_operand:SI 0 "register_operand" "=w")
5182 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
5183 (match_operand:QI 2 "register_operand" "w")]
5184 UNSPEC_USHL_2S))]
5185 "TARGET_SIMD"
5186 "ushl\t%0.2s, %1.2s, %2.2s"
5187 [(set_attr "type" "neon_shift_reg")]
5188 )
5189
5190 (define_insn "*aarch64_sisd_sshl"
5191 [(set (match_operand:DI 0 "register_operand" "=w")
5192 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
5193 (match_operand:QI 2 "register_operand" "w")]
5194 UNSPEC_SISD_SSHL))]
5195 "TARGET_SIMD"
5196 "sshl\t%d0, %d1, %d2"
5197 [(set_attr "type" "neon_shift_reg")]
5198 )
5199
5200 (define_insn "*aarch64_sshl_2s"
5201 [(set (match_operand:SI 0 "register_operand" "=w")
5202 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
5203 (match_operand:QI 2 "register_operand" "w")]
5204 UNSPEC_SSHL_2S))]
5205 "TARGET_SIMD"
5206 "sshl\t%0.2s, %1.2s, %2.2s"
5207 [(set_attr "type" "neon_shift_reg")]
5208 )
5209
5210 (define_insn "*aarch64_sisd_neg_qi"
5211 [(set (match_operand:QI 0 "register_operand" "=w")
5212 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
5213 UNSPEC_SISD_NEG))]
5214 "TARGET_SIMD"
5215 "neg\t%d0, %d1"
5216 [(set_attr "type" "neon_neg")]
5217 )
5218
5219 ;; Rotate right
5220 (define_insn "*ror<mode>3_insn"
5221 [(set (match_operand:GPI 0 "register_operand" "=r,r")
5222 (rotatert:GPI
5223 (match_operand:GPI 1 "register_operand" "r,r")
5224 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
5225 ""
5226 "@
5227 ror\\t%<w>0, %<w>1, %2
5228 ror\\t%<w>0, %<w>1, %<w>2"
5229 [(set_attr "type" "rotate_imm,shift_reg")]
5230 )
5231
5232 ;; zero_extend version of above
5233 (define_insn "*<optab>si3_insn_uxtw"
5234 [(set (match_operand:DI 0 "register_operand" "=r,r")
5235 (zero_extend:DI (SHIFT:SI
5236 (match_operand:SI 1 "register_operand" "r,r")
5237 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
5238 ""
5239 "@
5240 <shift>\\t%w0, %w1, %2
5241 <shift>\\t%w0, %w1, %w2"
5242 [(set_attr "type" "bfx,shift_reg")]
5243 )
5244
5245 (define_insn "*<optab><mode>3_insn"
5246 [(set (match_operand:SHORT 0 "register_operand" "=r")
5247 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
5248 (match_operand 2 "const_int_operand" "n")))]
5249 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
5250 {
5251 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5252 return "<bfshift>\t%w0, %w1, %2, %3";
5253 }
5254 [(set_attr "type" "bfx")]
5255 )
5256
5257 (define_insn "*extr<mode>5_insn"
5258 [(set (match_operand:GPI 0 "register_operand" "=r")
5259 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5260 (match_operand 3 "const_int_operand" "n"))
5261 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
5262 (match_operand 4 "const_int_operand" "n"))))]
5263 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
5264 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
5265 "extr\\t%<w>0, %<w>1, %<w>2, %4"
5266 [(set_attr "type" "rotate_imm")]
5267 )
5268
5269 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
5270 ;; so we have to match both orderings.
5271 (define_insn "*extr<mode>5_insn_alt"
5272 [(set (match_operand:GPI 0 "register_operand" "=r")
5273 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
5274 (match_operand 4 "const_int_operand" "n"))
5275 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5276 (match_operand 3 "const_int_operand" "n"))))]
5277 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
5278 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
5279 == GET_MODE_BITSIZE (<MODE>mode))"
5280 "extr\\t%<w>0, %<w>1, %<w>2, %4"
5281 [(set_attr "type" "rotate_imm")]
5282 )
5283
5284 ;; zero_extend version of the above
5285 (define_insn "*extrsi5_insn_uxtw"
5286 [(set (match_operand:DI 0 "register_operand" "=r")
5287 (zero_extend:DI
5288 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
5289 (match_operand 3 "const_int_operand" "n"))
5290 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
5291 (match_operand 4 "const_int_operand" "n")))))]
5292 "UINTVAL (operands[3]) < 32 &&
5293 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
5294 "extr\\t%w0, %w1, %w2, %4"
5295 [(set_attr "type" "rotate_imm")]
5296 )
5297
5298 (define_insn "*extrsi5_insn_uxtw_alt"
5299 [(set (match_operand:DI 0 "register_operand" "=r")
5300 (zero_extend:DI
5301 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
5302 (match_operand 4 "const_int_operand" "n"))
5303 (ashift:SI (match_operand:SI 1 "register_operand" "r")
5304 (match_operand 3 "const_int_operand" "n")))))]
5305 "UINTVAL (operands[3]) < 32 &&
5306 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
5307 "extr\\t%w0, %w1, %w2, %4"
5308 [(set_attr "type" "rotate_imm")]
5309 )
5310
5311 (define_insn "*ror<mode>3_insn"
5312 [(set (match_operand:GPI 0 "register_operand" "=r")
5313 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
5314 (match_operand 2 "const_int_operand" "n")))]
5315 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
5316 {
5317 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5318 return "ror\\t%<w>0, %<w>1, %3";
5319 }
5320 [(set_attr "type" "rotate_imm")]
5321 )
5322
5323 ;; zero_extend version of the above
5324 (define_insn "*rorsi3_insn_uxtw"
5325 [(set (match_operand:DI 0 "register_operand" "=r")
5326 (zero_extend:DI
5327 (rotate:SI (match_operand:SI 1 "register_operand" "r")
5328 (match_operand 2 "const_int_operand" "n"))))]
5329 "UINTVAL (operands[2]) < 32"
5330 {
5331 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
5332 return "ror\\t%w0, %w1, %3";
5333 }
5334 [(set_attr "type" "rotate_imm")]
5335 )
5336
5337 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
5338 [(set (match_operand:GPI 0 "register_operand" "=r")
5339 (ANY_EXTEND:GPI
5340 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
5341 (match_operand 2 "const_int_operand" "n"))))]
5342 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5343 {
5344 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
5345 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5346 }
5347 [(set_attr "type" "bfx")]
5348 )
5349
5350 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
5351 [(set (match_operand:GPI 0 "register_operand" "=r")
5352 (zero_extend:GPI
5353 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
5354 (match_operand 2 "const_int_operand" "n"))))]
5355 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5356 {
5357 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
5358 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5359 }
5360 [(set_attr "type" "bfx")]
5361 )
5362
5363 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
5364 [(set (match_operand:GPI 0 "register_operand" "=r")
5365 (sign_extend:GPI
5366 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
5367 (match_operand 2 "const_int_operand" "n"))))]
5368 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5369 {
5370 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
5371 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5372 }
5373 [(set_attr "type" "bfx")]
5374 )
5375
5376 ;; -------------------------------------------------------------------
5377 ;; Bitfields
5378 ;; -------------------------------------------------------------------
5379
5380 (define_expand "<optab>"
5381 [(set (match_operand:DI 0 "register_operand")
5382 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
5383 (match_operand 2
5384 "aarch64_simd_shift_imm_offset_di")
5385 (match_operand 3 "aarch64_simd_shift_imm_di")))]
5386 ""
5387 {
5388 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5389 1, GET_MODE_BITSIZE (DImode) - 1))
5390 FAIL;
5391 }
5392 )
5393
5394
5395 (define_insn "*<optab><mode>"
5396 [(set (match_operand:GPI 0 "register_operand" "=r")
5397 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
5398 (match_operand 2
5399 "aarch64_simd_shift_imm_offset_<mode>" "n")
5400 (match_operand 3
5401 "aarch64_simd_shift_imm_<mode>" "n")))]
5402 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5403 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
5404 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
5405 [(set_attr "type" "bfx")]
5406 )
5407
5408 ;; When the bit position and width add up to 32 we can use a W-reg LSR
5409 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
5410 (define_split
5411 [(set (match_operand:DI 0 "register_operand")
5412 (zero_extract:DI (match_operand:DI 1 "register_operand")
5413 (match_operand 2
5414 "aarch64_simd_shift_imm_offset_di")
5415 (match_operand 3
5416 "aarch64_simd_shift_imm_di")))]
5417 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
5418 GET_MODE_BITSIZE (DImode) - 1)
5419 && (INTVAL (operands[2]) + INTVAL (operands[3]))
5420 == GET_MODE_BITSIZE (SImode)"
5421 [(set (match_dup 0)
5422 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
5423 {
5424 operands[4] = gen_lowpart (SImode, operands[1]);
5425 }
5426 )
5427
5428 ;; Bitfield Insert (insv)
5429 (define_expand "insv<mode>"
5430 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
5431 (match_operand 1 "const_int_operand")
5432 (match_operand 2 "const_int_operand"))
5433 (match_operand:GPI 3 "general_operand"))]
5434 ""
5435 {
5436 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
5437 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
5438 rtx value = operands[3];
5439
5440 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
5441 FAIL;
5442
5443 if (CONST_INT_P (value))
5444 {
5445 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
5446
5447 /* Prefer AND/OR for inserting all zeros or all ones. */
5448 if ((UINTVAL (value) & mask) == 0
5449 || (UINTVAL (value) & mask) == mask)
5450 FAIL;
5451
5452 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
5453 if (width == 16 && (pos % 16) == 0)
5454 DONE;
5455 }
5456 operands[3] = force_reg (<MODE>mode, value);
5457 })
5458
5459 (define_insn "*insv_reg<mode>"
5460 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
5461 (match_operand 1 "const_int_operand" "n")
5462 (match_operand 2 "const_int_operand" "n"))
5463 (match_operand:GPI 3 "register_operand" "r"))]
5464 "!(UINTVAL (operands[1]) == 0
5465 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
5466 > GET_MODE_BITSIZE (<MODE>mode)))"
5467 "bfi\\t%<w>0, %<w>3, %2, %1"
5468 [(set_attr "type" "bfm")]
5469 )
5470
5471 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
5472 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
5473 (match_operand 1 "const_int_operand" "n")
5474 (match_operand 2 "const_int_operand" "n"))
5475 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
5476 "UINTVAL (operands[1]) <= <ALLX:sizen>"
5477 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
5478 [(set_attr "type" "bfm")]
5479 )
5480
5481 ;; Match a bfi instruction where the shift of OP3 means that we are
5482 ;; actually copying the least significant bits of OP3 into OP0 by way
5483 ;; of the AND masks and the IOR instruction. A similar instruction
5484 ;; with the two parts of the IOR swapped around was never triggered
5485 ;; in a bootstrap build and test of GCC so it was not included.
5486
5487 (define_insn "*aarch64_bfi<GPI:mode>5_shift"
5488 [(set (match_operand:GPI 0 "register_operand" "=r")
5489 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
5490 (match_operand:GPI 2 "const_int_operand" "n"))
5491 (and:GPI (ashift:GPI
5492 (match_operand:GPI 3 "register_operand" "r")
5493 (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n"))
5494 (match_operand:GPI 5 "const_int_operand" "n"))))]
5495 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]),
5496 UINTVAL (operands[4]),
5497 UINTVAL(operands[5]))"
5498 "bfi\t%<GPI:w>0, %<GPI:w>3, %4, %P5"
5499 [(set_attr "type" "bfm")]
5500 )
5501
5502 (define_insn "*aarch64_bfi<GPI:mode>5_shift_alt"
5503 [(set (match_operand:GPI 0 "register_operand" "=r")
5504 (ior:GPI (and:GPI (ashift:GPI
5505 (match_operand:GPI 1 "register_operand" "r")
5506 (match_operand:GPI 2 "aarch64_simd_shift_imm_<mode>" "n"))
5507 (match_operand:GPI 3 "const_int_operand" "n"))
5508 (and:GPI (match_operand:GPI 4 "register_operand" "0")
5509 (match_operand:GPI 5 "const_int_operand" "n"))))]
5510 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[5]),
5511 UINTVAL (operands[2]),
5512 UINTVAL(operands[3]))"
5513 "bfi\t%<GPI:w>0, %<GPI:w>1, %2, %P3"
5514 [(set_attr "type" "bfm")]
5515 )
5516
5517 ;; Like *aarch64_bfi<GPI:mode>5_shift but with no and of the ashift because
5518 ;; the shift is large enough to remove the need for an AND instruction.
5519
5520 (define_insn "*aarch64_bfi<GPI:mode>4_noand"
5521 [(set (match_operand:GPI 0 "register_operand" "=r")
5522 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
5523 (match_operand:GPI 2 "const_int_operand" "n"))
5524 (ashift:GPI
5525 (match_operand:GPI 3 "register_operand" "r")
5526 (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n"))))]
5527 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]),
5528 UINTVAL (operands[4]),
5529 HOST_WIDE_INT_M1U << UINTVAL (operands[4]) )"
5530 {
5531 operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[4]));
5532 return "bfi\t%<GPI:w>0, %<GPI:w>3, %4, %5";
5533 }
5534 [(set_attr "type" "bfm")]
5535 )
5536
5537 (define_insn "*aarch64_bfi<GPI:mode>4_noand_alt"
5538 [(set (match_operand:GPI 0 "register_operand" "=r")
5539 (ior:GPI (ashift:GPI
5540 (match_operand:GPI 1 "register_operand" "r")
5541 (match_operand:GPI 2 "aarch64_simd_shift_imm_<mode>" "n"))
5542 (and:GPI (match_operand:GPI 3 "register_operand" "0")
5543 (match_operand:GPI 4 "const_int_operand" "n"))))]
5544 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[4]),
5545 UINTVAL (operands[2]),
5546 HOST_WIDE_INT_M1U << UINTVAL (operands[2]) )"
5547 {
5548 operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[2]));
5549 return "bfi\t%<GPI:w>0, %<GPI:w>1, %2, %5";
5550 }
5551 [(set_attr "type" "bfm")]
5552 )
5553
5554 ;; Like *aarch64_bfi<GPI:mode>5_shift but with no shifting, we are just
5555 ;; copying the least significant bits of OP3 to OP0. We need two versions
5556 ;; of the instruction to handle different checks on the constant values.
5557
5558 (define_insn "*aarch64_bfi<GPI:mode>4_noshift"
5559 [(set (match_operand:GPI 0 "register_operand" "=r")
5560 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
5561 (match_operand:GPI 2 "const_int_operand" "n"))
5562 (and:GPI (match_operand:GPI 3 "register_operand" "r")
5563 (match_operand:GPI 4 "const_int_operand" "n"))))]
5564 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]), 0,
5565 UINTVAL (operands[4]))"
5566 "bfi\t%<GPI:w>0, %<GPI:w>3, 0, %P4"
5567 [(set_attr "type" "bfm")]
5568 )
5569
5570 (define_insn "*aarch64_bfi<GPI:mode>4_noshift_alt"
5571 [(set (match_operand:GPI 0 "register_operand" "=r")
5572 (ior:GPI (and:GPI (match_operand:GPI 3 "register_operand" "r")
5573 (match_operand:GPI 4 "const_int_operand" "n"))
5574 (and:GPI (match_operand:GPI 1 "register_operand" "0")
5575 (match_operand:GPI 2 "const_int_operand" "n"))))]
5576 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]), 0,
5577 UINTVAL (operands[4]))"
5578 "bfi\t%<GPI:w>0, %<GPI:w>3, 0, %P4"
5579 [(set_attr "type" "bfm")]
5580 )
5581
5582 (define_insn "*extr_insv_lower_reg<mode>"
5583 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
5584 (match_operand 1 "const_int_operand" "n")
5585 (const_int 0))
5586 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
5587 (match_dup 1)
5588 (match_operand 3 "const_int_operand" "n")))]
5589 "!(UINTVAL (operands[1]) == 0
5590 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
5591 > GET_MODE_BITSIZE (<MODE>mode)))"
5592 "bfxil\\t%<w>0, %<w>2, %3, %1"
5593 [(set_attr "type" "bfm")]
5594 )
5595
5596 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
5597 [(set (match_operand:GPI 0 "register_operand" "=r")
5598 (ashift:GPI (ANY_EXTEND:GPI
5599 (match_operand:ALLX 1 "register_operand" "r"))
5600 (match_operand 2 "const_int_operand" "n")))]
5601 "UINTVAL (operands[2]) < <GPI:sizen>"
5602 {
5603 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
5604 ? GEN_INT (<ALLX:sizen>)
5605 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
5606 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5607 }
5608 [(set_attr "type" "bfx")]
5609 )
5610
5611 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
5612
5613 (define_insn "*andim_ashift<mode>_bfiz"
5614 [(set (match_operand:GPI 0 "register_operand" "=r")
5615 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5616 (match_operand 2 "const_int_operand" "n"))
5617 (match_operand 3 "const_int_operand" "n")))]
5618 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
5619 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
5620 [(set_attr "type" "bfx")]
5621 )
5622
5623 ;; Match sbfiz pattern in a shift left + shift right operation.
5624
5625 (define_insn "*ashift<mode>_extv_bfiz"
5626 [(set (match_operand:GPI 0 "register_operand" "=r")
5627 (ashift:GPI (sign_extract:GPI (match_operand:GPI 1 "register_operand" "r")
5628 (match_operand 2 "aarch64_simd_shift_imm_offset_<mode>" "n")
5629 (const_int 0))
5630 (match_operand 3 "aarch64_simd_shift_imm_<mode>" "n")))]
5631 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5632 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
5633 "sbfiz\\t%<w>0, %<w>1, %3, %2"
5634 [(set_attr "type" "bfx")]
5635 )
5636
5637 (define_insn "*ashiftsi_extvdi_bfiz"
5638 [(set (match_operand:SI 0 "register_operand" "=r")
5639 (ashift:SI
5640 (match_operator:SI 4 "subreg_lowpart_operator"
5641 [(sign_extract:DI
5642 (match_operand:DI 1 "register_operand" "r")
5643 (match_operand 2 "aarch64_simd_shift_imm_offset_si")
5644 (const_int 0))])
5645 (match_operand 3 "aarch64_simd_shift_imm_si")))]
5646 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5647 1, GET_MODE_BITSIZE (SImode) - 1)"
5648 "sbfiz\\t%w0, %w1, %3, %2"
5649 [(set_attr "type" "bfx")]
5650 )
5651
5652 ;; When the bit position and width of the equivalent extraction add up to 32
5653 ;; we can use a W-reg LSL instruction taking advantage of the implicit
5654 ;; zero-extension of the X-reg.
5655 (define_split
5656 [(set (match_operand:DI 0 "register_operand")
5657 (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
5658 (match_operand 2 "const_int_operand"))
5659 (match_operand 3 "const_int_operand")))]
5660 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
5661 && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
5662 == GET_MODE_BITSIZE (SImode)"
5663 [(set (match_dup 0)
5664 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
5665 {
5666 operands[4] = gen_lowpart (SImode, operands[1]);
5667 }
5668 )
5669
5670 (define_insn "bswap<mode>2"
5671 [(set (match_operand:GPI 0 "register_operand" "=r")
5672 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
5673 ""
5674 "rev\\t%<w>0, %<w>1"
5675 [(set_attr "type" "rev")]
5676 )
5677
5678 (define_insn "bswaphi2"
5679 [(set (match_operand:HI 0 "register_operand" "=r")
5680 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
5681 ""
5682 "rev16\\t%w0, %w1"
5683 [(set_attr "type" "rev")]
5684 )
5685
5686 (define_insn "*aarch64_bfxil<mode>"
5687 [(set (match_operand:GPI 0 "register_operand" "=r,r")
5688 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "r,0")
5689 (match_operand:GPI 3 "const_int_operand" "n, Ulc"))
5690 (and:GPI (match_operand:GPI 2 "register_operand" "0,r")
5691 (match_operand:GPI 4 "const_int_operand" "Ulc, n"))))]
5692 "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
5693 && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
5694 || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
5695 {
5696 switch (which_alternative)
5697 {
5698 case 0:
5699 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
5700 return "bfxil\\t%<w>0, %<w>1, 0, %3";
5701 case 1:
5702 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
5703 return "bfxil\\t%<w>0, %<w>2, 0, %3";
5704 default:
5705 gcc_unreachable ();
5706 }
5707 }
5708 [(set_attr "type" "bfm")]
5709 )
5710
5711 ; Zero-extended version of above (aarch64_bfxil)
5712 (define_insn "*aarch64_bfxilsi_uxtw"
5713 [(set (match_operand:DI 0 "register_operand" "=r,r")
5714 (zero_extend:DI (ior:SI (and:SI (match_operand:SI 1 "register_operand"
5715 "r,0")
5716 (match_operand:SI 3 "const_int_operand" "n, Ulc"))
5717 (and:SI (match_operand:SI 2 "register_operand" "0,r")
5718 (match_operand:SI 4 "const_int_operand" "Ulc, n")))))]
5719 "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
5720 && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
5721 || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
5722 {
5723 switch (which_alternative)
5724 {
5725 case 0:
5726 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
5727 return "bfxil\\t%0, %1, 0, %3";
5728 case 1:
5729 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
5730 return "bfxil\\t%0, %2, 0, %3";
5731 default:
5732 gcc_unreachable ();
5733 }
5734 }
5735 [(set_attr "type" "bfm")]
5736 )
5737
5738 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
5739 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
5740 ;; each valid permutation.
5741
5742 (define_insn "rev16<mode>2"
5743 [(set (match_operand:GPI 0 "register_operand" "=r")
5744 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5745 (const_int 8))
5746 (match_operand:GPI 3 "const_int_operand" "n"))
5747 (and:GPI (lshiftrt:GPI (match_dup 1)
5748 (const_int 8))
5749 (match_operand:GPI 2 "const_int_operand" "n"))))]
5750 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
5751 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
5752 "rev16\\t%<w>0, %<w>1"
5753 [(set_attr "type" "rev")]
5754 )
5755
5756 (define_insn "rev16<mode>2_alt"
5757 [(set (match_operand:GPI 0 "register_operand" "=r")
5758 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
5759 (const_int 8))
5760 (match_operand:GPI 2 "const_int_operand" "n"))
5761 (and:GPI (ashift:GPI (match_dup 1)
5762 (const_int 8))
5763 (match_operand:GPI 3 "const_int_operand" "n"))))]
5764 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
5765 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
5766 "rev16\\t%<w>0, %<w>1"
5767 [(set_attr "type" "rev")]
5768 )
5769
5770 ;; zero_extend version of above
5771 (define_insn "*bswapsi2_uxtw"
5772 [(set (match_operand:DI 0 "register_operand" "=r")
5773 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
5774 ""
5775 "rev\\t%w0, %w1"
5776 [(set_attr "type" "rev")]
5777 )
5778
5779 ;; -------------------------------------------------------------------
5780 ;; Floating-point intrinsics
5781 ;; -------------------------------------------------------------------
5782
5783 ;; frint floating-point round to integral standard patterns.
5784 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
5785
5786 (define_insn "<frint_pattern><mode>2"
5787 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5788 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
5789 FRINT))]
5790 "TARGET_FLOAT"
5791 "frint<frint_suffix>\\t%<s>0, %<s>1"
5792 [(set_attr "type" "f_rint<stype>")]
5793 )
5794
5795 ;; frcvt floating-point round to integer and convert standard patterns.
5796 ;; Expands to lbtrunc, lceil, lfloor, lround.
5797 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
5798 [(set (match_operand:GPI 0 "register_operand" "=r")
5799 (FIXUORS:GPI
5800 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
5801 FCVT)))]
5802 "TARGET_FLOAT"
5803 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
5804 [(set_attr "type" "f_cvtf2i")]
5805 )
5806
5807 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
5808 [(set (match_operand:GPI 0 "register_operand" "=r")
5809 (FIXUORS:GPI
5810 (mult:GPF
5811 (match_operand:GPF 1 "register_operand" "w")
5812 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
5813 "TARGET_FLOAT
5814 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
5815 GET_MODE_BITSIZE (<GPI:MODE>mode))"
5816 {
5817 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
5818 char buf[64];
5819 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
5820 output_asm_insn (buf, operands);
5821 return "";
5822 }
5823 [(set_attr "type" "f_cvtf2i")]
5824 )
5825
5826 ;; fma - expand fma into patterns with the accumulator operand first since
5827 ;; reusing the accumulator results in better register allocation.
5828 ;; The register allocator considers copy preferences in operand order,
5829 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
5830
5831 (define_expand "fma<mode>4"
5832 [(set (match_operand:GPF_F16 0 "register_operand")
5833 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand")
5834 (match_operand:GPF_F16 2 "register_operand")
5835 (match_operand:GPF_F16 3 "register_operand")))]
5836 "TARGET_FLOAT"
5837 )
5838
5839 (define_insn "*aarch64_fma<mode>4"
5840 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5841 (fma:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w")
5842 (match_operand:GPF_F16 3 "register_operand" "w")
5843 (match_operand:GPF_F16 1 "register_operand" "w")))]
5844 "TARGET_FLOAT"
5845 "fmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5846 [(set_attr "type" "fmac<stype>")]
5847 )
5848
5849 (define_expand "fnma<mode>4"
5850 [(set (match_operand:GPF_F16 0 "register_operand")
5851 (fma:GPF_F16
5852 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand"))
5853 (match_operand:GPF_F16 2 "register_operand")
5854 (match_operand:GPF_F16 3 "register_operand")))]
5855 "TARGET_FLOAT"
5856 )
5857
5858 (define_insn "*aarch64_fnma<mode>4"
5859 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5860 (fma:GPF_F16
5861 (neg:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w"))
5862 (match_operand:GPF_F16 3 "register_operand" "w")
5863 (match_operand:GPF_F16 1 "register_operand" "w")))]
5864 "TARGET_FLOAT"
5865 "fmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
5866 [(set_attr "type" "fmac<stype>")]
5867 )
5868
5869
5870 (define_expand "fms<mode>4"
5871 [(set (match_operand:GPF 0 "register_operand")
5872 (fma:GPF (match_operand:GPF 1 "register_operand")
5873 (match_operand:GPF 2 "register_operand")
5874 (neg:GPF (match_operand:GPF 3 "register_operand"))))]
5875 "TARGET_FLOAT"
5876 )
5877
5878 (define_insn "*aarch64_fms<mode>4"
5879 [(set (match_operand:GPF 0 "register_operand" "=w")
5880 (fma:GPF (match_operand:GPF 2 "register_operand" "w")
5881 (match_operand:GPF 3 "register_operand" "w")
5882 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
5883 "TARGET_FLOAT"
5884 "fnmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
5885 [(set_attr "type" "fmac<s>")]
5886 )
5887
5888 (define_expand "fnms<mode>4"
5889 [(set (match_operand:GPF 0 "register_operand")
5890 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand"))
5891 (match_operand:GPF 2 "register_operand")
5892 (neg:GPF (match_operand:GPF 3 "register_operand"))))]
5893 "TARGET_FLOAT"
5894 )
5895
5896 (define_insn "*aarch64_fnms<mode>4"
5897 [(set (match_operand:GPF 0 "register_operand" "=w")
5898 (fma:GPF (neg:GPF (match_operand:GPF 2 "register_operand" "w"))
5899 (match_operand:GPF 3 "register_operand" "w")
5900 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
5901 "TARGET_FLOAT"
5902 "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5903 [(set_attr "type" "fmac<s>")]
5904 )
5905
5906 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
5907 (define_insn "*aarch64_fnmadd<mode>4"
5908 [(set (match_operand:GPF 0 "register_operand" "=w")
5909 (neg:GPF (fma:GPF (match_operand:GPF 2 "register_operand" "w")
5910 (match_operand:GPF 3 "register_operand" "w")
5911 (match_operand:GPF 1 "register_operand" "w"))))]
5912 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5913 "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5914 [(set_attr "type" "fmac<s>")]
5915 )
5916
5917 ;; -------------------------------------------------------------------
5918 ;; Floating-point conversions
5919 ;; -------------------------------------------------------------------
5920
5921 (define_insn "extendsfdf2"
5922 [(set (match_operand:DF 0 "register_operand" "=w")
5923 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
5924 "TARGET_FLOAT"
5925 "fcvt\\t%d0, %s1"
5926 [(set_attr "type" "f_cvt")]
5927 )
5928
5929 (define_insn "extendhfsf2"
5930 [(set (match_operand:SF 0 "register_operand" "=w")
5931 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
5932 "TARGET_FLOAT"
5933 "fcvt\\t%s0, %h1"
5934 [(set_attr "type" "f_cvt")]
5935 )
5936
5937 (define_insn "extendhfdf2"
5938 [(set (match_operand:DF 0 "register_operand" "=w")
5939 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
5940 "TARGET_FLOAT"
5941 "fcvt\\t%d0, %h1"
5942 [(set_attr "type" "f_cvt")]
5943 )
5944
5945 (define_insn "truncdfsf2"
5946 [(set (match_operand:SF 0 "register_operand" "=w")
5947 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
5948 "TARGET_FLOAT"
5949 "fcvt\\t%s0, %d1"
5950 [(set_attr "type" "f_cvt")]
5951 )
5952
5953 (define_insn "truncsfhf2"
5954 [(set (match_operand:HF 0 "register_operand" "=w")
5955 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
5956 "TARGET_FLOAT"
5957 "fcvt\\t%h0, %s1"
5958 [(set_attr "type" "f_cvt")]
5959 )
5960
5961 (define_insn "truncdfhf2"
5962 [(set (match_operand:HF 0 "register_operand" "=w")
5963 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
5964 "TARGET_FLOAT"
5965 "fcvt\\t%h0, %d1"
5966 [(set_attr "type" "f_cvt")]
5967 )
5968
5969 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
5970 ;; and making r = w more expensive
5971
5972 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>2"
5973 [(set (match_operand:GPI 0 "register_operand" "=w,?r")
5974 (FIXUORS:GPI (match_operand:<FCVT_TARGET> 1 "register_operand" "w,w")))]
5975 "TARGET_FLOAT"
5976 "@
5977 fcvtz<su>\t%<s>0, %<s>1
5978 fcvtz<su>\t%<w>0, %<s>1"
5979 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
5980 )
5981
5982 ;; Convert HF -> SI or DI
5983
5984 (define_insn "<optab>_trunchf<GPI:mode>2"
5985 [(set (match_operand:GPI 0 "register_operand" "=r")
5986 (FIXUORS:GPI (match_operand:HF 1 "register_operand" "w")))]
5987 "TARGET_FP_F16INST"
5988 "fcvtz<su>\t%<w>0, %h1"
5989 [(set_attr "type" "f_cvtf2i")]
5990 )
5991
5992 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
5993 ;; input in a fp register and output in a integer register
5994
5995 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>2"
5996 [(set (match_operand:GPI 0 "register_operand" "=r")
5997 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE> 1 "register_operand" "w")))]
5998 "TARGET_FLOAT"
5999 "fcvtz<su>\t%<w>0, %<fpw>1"
6000 [(set_attr "type" "f_cvtf2i")]
6001 )
6002
6003 (define_insn "*fix_to_zero_extend<mode>di2"
6004 [(set (match_operand:DI 0 "register_operand" "=r")
6005 (zero_extend:DI
6006 (unsigned_fix:SI
6007 (match_operand:GPF 1 "register_operand" "w"))))]
6008 "TARGET_FLOAT"
6009 "fcvtzu\t%w0, %<s>1"
6010 [(set_attr "type" "f_cvtf2i")]
6011 )
6012
6013 ;; Equal width integer to fp and multiply combine.
6014 (define_insn "*aarch64_<su_optab>cvtf<fcvt_target><GPF:mode>2_mult"
6015 [(set (match_operand:GPF 0 "register_operand" "=w,w")
6016 (mult:GPF (FLOATUORS:GPF
6017 (match_operand:<FCVT_TARGET> 1 "register_operand" "w,?r"))
6018 (match_operand:GPF 2 "aarch64_fp_pow2_recip" "Dt,Dt")))]
6019 "TARGET_FLOAT"
6020 {
6021 operands[2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[2]));
6022 switch (which_alternative)
6023 {
6024 case 0:
6025 return "<su_optab>cvtf\t%<GPF:s>0, %<s>1, #%2";
6026 case 1:
6027 return "<su_optab>cvtf\t%<GPF:s>0, %<w1>1, #%2";
6028 default:
6029 gcc_unreachable ();
6030 }
6031 }
6032 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6033 (set_attr "arch" "simd,fp")]
6034 )
6035
6036 ;; Unequal width integer to fp and multiply combine.
6037 (define_insn "*aarch64_<su_optab>cvtf<fcvt_iesize><GPF:mode>2_mult"
6038 [(set (match_operand:GPF 0 "register_operand" "=w")
6039 (mult:GPF (FLOATUORS:GPF
6040 (match_operand:<FCVT_IESIZE> 1 "register_operand" "r"))
6041 (match_operand:GPF 2 "aarch64_fp_pow2_recip" "Dt")))]
6042 "TARGET_FLOAT"
6043 {
6044 operands[2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[2]));
6045 return "<su_optab>cvtf\t%<GPF:s>0, %<w2>1, #%2";
6046 }
6047 [(set_attr "type" "f_cvti2f")]
6048 )
6049
6050 ;; Equal width integer to fp conversion.
6051 (define_insn "<optab><fcvt_target><GPF:mode>2"
6052 [(set (match_operand:GPF 0 "register_operand" "=w,w")
6053 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,?r")))]
6054 "TARGET_FLOAT"
6055 "@
6056 <su_optab>cvtf\t%<GPF:s>0, %<s>1
6057 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
6058 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6059 (set_attr "arch" "simd,fp")]
6060 )
6061
6062 ;; Unequal width integer to fp conversions.
6063 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
6064 [(set (match_operand:GPF 0 "register_operand" "=w")
6065 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
6066 "TARGET_FLOAT"
6067 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
6068 [(set_attr "type" "f_cvti2f")]
6069 )
6070
6071 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
6072 ;; midend will arrange for an SImode conversion to HFmode to first go
6073 ;; through DFmode, then to HFmode. But first it will try converting
6074 ;; to DImode then down, which would match our DImode pattern below and
6075 ;; give very poor code-generation. So, we must provide our own emulation
6076 ;; of the mid-end logic.
6077
6078 (define_insn "aarch64_fp16_<optab><mode>hf2"
6079 [(set (match_operand:HF 0 "register_operand" "=w")
6080 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
6081 "TARGET_FP_F16INST"
6082 "<su_optab>cvtf\t%h0, %<w>1"
6083 [(set_attr "type" "f_cvti2f")]
6084 )
6085
6086 (define_expand "<optab>sihf2"
6087 [(set (match_operand:HF 0 "register_operand")
6088 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
6089 "TARGET_FLOAT"
6090 {
6091 if (TARGET_FP_F16INST)
6092 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
6093 else
6094 {
6095 rtx convert_target = gen_reg_rtx (DFmode);
6096 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
6097 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
6098 }
6099 DONE;
6100 }
6101 )
6102
6103 ;; For DImode there is no wide enough floating-point mode that we
6104 ;; can convert through natively (TFmode would work, but requires a library
6105 ;; call). However, we know that any value >= 65504 will be rounded
6106 ;; to infinity on conversion. This is well within the range of SImode, so
6107 ;; we can:
6108 ;; Saturate to SImode.
6109 ;; Convert from that to DFmode
6110 ;; Convert from that to HFmode (phew!).
6111 ;; Note that the saturation to SImode requires the SIMD extensions. If
6112 ;; we ever need to provide this pattern where the SIMD extensions are not
6113 ;; available, we would need a different approach.
6114
6115 (define_expand "<optab>dihf2"
6116 [(set (match_operand:HF 0 "register_operand")
6117 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
6118 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
6119 {
6120 if (TARGET_FP_F16INST)
6121 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
6122 else
6123 {
6124 rtx sat_target = gen_reg_rtx (SImode);
6125 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
6126 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
6127 }
6128
6129 DONE;
6130 }
6131 )
6132
6133 ;; Convert between fixed-point and floating-point (scalar modes)
6134
6135 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
6136 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
6137 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
6138 (match_operand:SI 2 "immediate_operand" "i, i")]
6139 FCVT_F2FIXED))]
6140 ""
6141 "@
6142 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
6143 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
6144 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
6145 (set_attr "arch" "fp,simd")]
6146 )
6147
6148 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
6149 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
6150 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
6151 (match_operand:SI 2 "immediate_operand" "i, i")]
6152 FCVT_FIXED2F))]
6153 ""
6154 "@
6155 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
6156 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
6157 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
6158 (set_attr "arch" "fp,simd")]
6159 )
6160
6161 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
6162 [(set (match_operand:GPI 0 "register_operand" "=r")
6163 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
6164 (match_operand:SI 2 "immediate_operand" "i")]
6165 FCVT_F2FIXED))]
6166 "TARGET_FP_F16INST"
6167 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
6168 [(set_attr "type" "f_cvtf2i")]
6169 )
6170
6171 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
6172 [(set (match_operand:HF 0 "register_operand" "=w")
6173 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
6174 (match_operand:SI 2 "immediate_operand" "i")]
6175 FCVT_FIXED2F))]
6176 "TARGET_FP_F16INST"
6177 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
6178 [(set_attr "type" "f_cvti2f")]
6179 )
6180
6181 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
6182 [(set (match_operand:HI 0 "register_operand" "=w")
6183 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
6184 (match_operand:SI 2 "immediate_operand" "i")]
6185 FCVT_F2FIXED))]
6186 "TARGET_SIMD"
6187 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
6188 [(set_attr "type" "neon_fp_to_int_s")]
6189 )
6190
6191 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
6192 [(set (match_operand:HF 0 "register_operand" "=w")
6193 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
6194 (match_operand:SI 2 "immediate_operand" "i")]
6195 FCVT_FIXED2F))]
6196 "TARGET_SIMD"
6197 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
6198 [(set_attr "type" "neon_int_to_fp_s")]
6199 )
6200
6201 ;; -------------------------------------------------------------------
6202 ;; Floating-point arithmetic
6203 ;; -------------------------------------------------------------------
6204
6205 (define_insn "add<mode>3"
6206 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6207 (plus:GPF_F16
6208 (match_operand:GPF_F16 1 "register_operand" "w")
6209 (match_operand:GPF_F16 2 "register_operand" "w")))]
6210 "TARGET_FLOAT"
6211 "fadd\\t%<s>0, %<s>1, %<s>2"
6212 [(set_attr "type" "fadd<stype>")]
6213 )
6214
6215 (define_insn "sub<mode>3"
6216 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6217 (minus:GPF_F16
6218 (match_operand:GPF_F16 1 "register_operand" "w")
6219 (match_operand:GPF_F16 2 "register_operand" "w")))]
6220 "TARGET_FLOAT"
6221 "fsub\\t%<s>0, %<s>1, %<s>2"
6222 [(set_attr "type" "fadd<stype>")]
6223 )
6224
6225 (define_insn "mul<mode>3"
6226 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6227 (mult:GPF_F16
6228 (match_operand:GPF_F16 1 "register_operand" "w")
6229 (match_operand:GPF_F16 2 "register_operand" "w")))]
6230 "TARGET_FLOAT"
6231 "fmul\\t%<s>0, %<s>1, %<s>2"
6232 [(set_attr "type" "fmul<stype>")]
6233 )
6234
6235 (define_insn "*fnmul<mode>3"
6236 [(set (match_operand:GPF 0 "register_operand" "=w")
6237 (mult:GPF
6238 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
6239 (match_operand:GPF 2 "register_operand" "w")))]
6240 "TARGET_FLOAT && !flag_rounding_math"
6241 "fnmul\\t%<s>0, %<s>1, %<s>2"
6242 [(set_attr "type" "fmul<s>")]
6243 )
6244
6245 (define_insn "*fnmul<mode>3"
6246 [(set (match_operand:GPF 0 "register_operand" "=w")
6247 (neg:GPF (mult:GPF
6248 (match_operand:GPF 1 "register_operand" "w")
6249 (match_operand:GPF 2 "register_operand" "w"))))]
6250 "TARGET_FLOAT"
6251 "fnmul\\t%<s>0, %<s>1, %<s>2"
6252 [(set_attr "type" "fmul<s>")]
6253 )
6254
6255 (define_expand "div<mode>3"
6256 [(set (match_operand:GPF_F16 0 "register_operand")
6257 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
6258 (match_operand:GPF_F16 2 "register_operand")))]
6259 "TARGET_FLOAT"
6260 {
6261 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
6262 DONE;
6263
6264 operands[1] = force_reg (<MODE>mode, operands[1]);
6265 })
6266
6267 (define_insn "*div<mode>3"
6268 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6269 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
6270 (match_operand:GPF_F16 2 "register_operand" "w")))]
6271 "TARGET_FLOAT"
6272 "fdiv\\t%<s>0, %<s>1, %<s>2"
6273 [(set_attr "type" "fdiv<stype>")]
6274 )
6275
6276 (define_insn "neg<mode>2"
6277 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6278 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6279 "TARGET_FLOAT"
6280 "fneg\\t%<s>0, %<s>1"
6281 [(set_attr "type" "ffarith<stype>")]
6282 )
6283
6284 (define_expand "sqrt<mode>2"
6285 [(set (match_operand:GPF_F16 0 "register_operand")
6286 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand")))]
6287 "TARGET_FLOAT"
6288 {
6289 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
6290 DONE;
6291 })
6292
6293 (define_insn "*sqrt<mode>2"
6294 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6295 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6296 "TARGET_FLOAT"
6297 "fsqrt\\t%<s>0, %<s>1"
6298 [(set_attr "type" "fsqrt<stype>")]
6299 )
6300
6301 (define_insn "abs<mode>2"
6302 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6303 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6304 "TARGET_FLOAT"
6305 "fabs\\t%<s>0, %<s>1"
6306 [(set_attr "type" "ffarith<stype>")]
6307 )
6308
6309 ;; Given that smax/smin do not specify the result when either input is NaN,
6310 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
6311 ;; for smin.
6312
6313 (define_insn "smax<mode>3"
6314 [(set (match_operand:GPF 0 "register_operand" "=w")
6315 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
6316 (match_operand:GPF 2 "register_operand" "w")))]
6317 "TARGET_FLOAT"
6318 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
6319 [(set_attr "type" "f_minmax<s>")]
6320 )
6321
6322 (define_insn "smin<mode>3"
6323 [(set (match_operand:GPF 0 "register_operand" "=w")
6324 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
6325 (match_operand:GPF 2 "register_operand" "w")))]
6326 "TARGET_FLOAT"
6327 "fminnm\\t%<s>0, %<s>1, %<s>2"
6328 [(set_attr "type" "f_minmax<s>")]
6329 )
6330
6331 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
6332 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
6333 ;; which implement the IEEE fmax ()/fmin () functions.
6334 (define_insn "<maxmin_uns><mode>3"
6335 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6336 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
6337 (match_operand:GPF_F16 2 "register_operand" "w")]
6338 FMAXMIN_UNS))]
6339 "TARGET_FLOAT"
6340 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
6341 [(set_attr "type" "f_minmax<stype>")]
6342 )
6343
6344 (define_expand "lrint<GPF:mode><GPI:mode>2"
6345 [(match_operand:GPI 0 "register_operand")
6346 (match_operand:GPF 1 "register_operand")]
6347 "TARGET_FLOAT
6348 && ((GET_MODE_BITSIZE (<GPF:MODE>mode) <= LONG_TYPE_SIZE)
6349 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
6350 {
6351 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
6352 emit_insn (gen_rint<GPF:mode>2 (cvt, operands[1]));
6353 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>2 (operands[0], cvt));
6354 DONE;
6355 }
6356 )
6357
6358 ;; For copysign (x, y), we want to generate:
6359 ;;
6360 ;; LDR d2, #(1 << 63)
6361 ;; BSL v2.8b, [y], [x]
6362 ;;
6363 ;; or another, equivalent, sequence using one of BSL/BIT/BIF. Because
6364 ;; we expect these operations to nearly always operate on
6365 ;; floating-point values, we do not want the operation to be
6366 ;; simplified into a bit-field insert operation that operates on the
6367 ;; integer side, since typically that would involve three inter-bank
6368 ;; register copies. As we do not expect copysign to be followed by
6369 ;; other logical operations on the result, it seems preferable to keep
6370 ;; this as an unspec operation, rather than exposing the underlying
6371 ;; logic to the compiler.
6372
6373 (define_expand "copysign<GPF:mode>3"
6374 [(match_operand:GPF 0 "register_operand")
6375 (match_operand:GPF 1 "register_operand")
6376 (match_operand:GPF 2 "register_operand")]
6377 "TARGET_FLOAT && TARGET_SIMD"
6378 {
6379 rtx bitmask = gen_reg_rtx (<V_INT_EQUIV>mode);
6380 emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U
6381 << (GET_MODE_BITSIZE (<MODE>mode) - 1)));
6382 emit_insn (gen_copysign<mode>3_insn (operands[0], operands[1], operands[2],
6383 bitmask));
6384 DONE;
6385 }
6386 )
6387
6388 (define_insn "copysign<GPF:mode>3_insn"
6389 [(set (match_operand:GPF 0 "register_operand" "=w,w,w,r")
6390 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w,0,w,r")
6391 (match_operand:GPF 2 "register_operand" "w,w,0,0")
6392 (match_operand:<V_INT_EQUIV> 3 "register_operand" "0,w,w,X")]
6393 UNSPEC_COPYSIGN))]
6394 "TARGET_FLOAT && TARGET_SIMD"
6395 "@
6396 bsl\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>
6397 bit\\t%0.<Vbtype>, %2.<Vbtype>, %3.<Vbtype>
6398 bif\\t%0.<Vbtype>, %1.<Vbtype>, %3.<Vbtype>
6399 bfxil\\t%<w1>0, %<w1>1, #0, <sizem1>"
6400 [(set_attr "type" "neon_bsl<q>,neon_bsl<q>,neon_bsl<q>,bfm")]
6401 )
6402
6403
6404 ;; For xorsign (x, y), we want to generate:
6405 ;;
6406 ;; LDR d2, #1<<63
6407 ;; AND v3.8B, v1.8B, v2.8B
6408 ;; EOR v0.8B, v0.8B, v3.8B
6409 ;;
6410
6411 (define_expand "xorsign<mode>3"
6412 [(match_operand:GPF 0 "register_operand")
6413 (match_operand:GPF 1 "register_operand")
6414 (match_operand:GPF 2 "register_operand")]
6415 "TARGET_FLOAT && TARGET_SIMD"
6416 {
6417
6418 machine_mode imode = <V_INT_EQUIV>mode;
6419 rtx mask = gen_reg_rtx (imode);
6420 rtx op1x = gen_reg_rtx (imode);
6421 rtx op2x = gen_reg_rtx (imode);
6422
6423 int bits = GET_MODE_BITSIZE (<MODE>mode) - 1;
6424 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
6425 imode)));
6426
6427 emit_insn (gen_and<v_int_equiv>3 (op2x, mask,
6428 lowpart_subreg (imode, operands[2],
6429 <MODE>mode)));
6430 emit_insn (gen_xor<v_int_equiv>3 (op1x,
6431 lowpart_subreg (imode, operands[1],
6432 <MODE>mode),
6433 op2x));
6434 emit_move_insn (operands[0],
6435 lowpart_subreg (<MODE>mode, op1x, imode));
6436 DONE;
6437 }
6438 )
6439
6440 ;; -------------------------------------------------------------------
6441 ;; Reload support
6442 ;; -------------------------------------------------------------------
6443 ;; Reload Scalar Floating point modes from constant pool.
6444 ;; The AArch64 port doesn't have __int128 constant move support.
6445 ;; The patterns need constraints due to TARGET_SECONDARY_RELOAD hook.
6446 (define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
6447 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
6448 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
6449 (clobber (match_operand:P 2 "register_operand" "=&r"))]
6450 "TARGET_FLOAT"
6451 {
6452 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
6453 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
6454 DONE;
6455 }
6456 )
6457
6458 ;; Reload Vector modes from constant pool.
6459 (define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
6460 [(set (match_operand:VALL 0 "register_operand" "=w")
6461 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
6462 (clobber (match_operand:P 2 "register_operand" "=&r"))]
6463 "TARGET_FLOAT"
6464 {
6465 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
6466 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
6467 DONE;
6468 }
6469 )
6470
6471 (define_expand "@aarch64_reload_mov<mode>"
6472 [(set (match_operand:TX 0 "register_operand" "=w")
6473 (match_operand:TX 1 "register_operand" "w"))
6474 (clobber (match_operand:DI 2 "register_operand" "=&r"))
6475 ]
6476 "TARGET_FLOAT"
6477 {
6478 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
6479 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
6480 gen_aarch64_movtilow_tilow (op0, op1);
6481 gen_aarch64_movdi_tihigh (operands[2], op1);
6482 gen_aarch64_movtihigh_di (op0, operands[2]);
6483 DONE;
6484 }
6485 )
6486
6487 ;; The following secondary reload helpers patterns are invoked
6488 ;; after or during reload as we don't want these patterns to start
6489 ;; kicking in during the combiner.
6490
6491 (define_insn "@aarch64_movdi_<mode>low"
6492 [(set (match_operand:DI 0 "register_operand" "=r")
6493 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
6494 (const_int 64) (const_int 0)))]
6495 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6496 "fmov\\t%x0, %d1"
6497 [(set_attr "type" "f_mrc")
6498 (set_attr "length" "4")
6499 ])
6500
6501 (define_insn "@aarch64_movdi_<mode>high"
6502 [(set (match_operand:DI 0 "register_operand" "=r")
6503 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
6504 (const_int 64) (const_int 64)))]
6505 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6506 "fmov\\t%x0, %1.d[1]"
6507 [(set_attr "type" "f_mrc")
6508 (set_attr "length" "4")
6509 ])
6510
6511 (define_insn "@aarch64_mov<mode>high_di"
6512 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
6513 (const_int 64) (const_int 64))
6514 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
6515 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6516 "fmov\\t%0.d[1], %x1"
6517 [(set_attr "type" "f_mcr")
6518 (set_attr "length" "4")
6519 ])
6520
6521 (define_insn "@aarch64_mov<mode>low_di"
6522 [(set (match_operand:TX 0 "register_operand" "=w")
6523 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
6524 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6525 "fmov\\t%d0, %x1"
6526 [(set_attr "type" "f_mcr")
6527 (set_attr "length" "4")
6528 ])
6529
6530 (define_insn "aarch64_movtilow_tilow"
6531 [(set (match_operand:TI 0 "register_operand" "=w")
6532 (zero_extend:TI
6533 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
6534 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6535 "fmov\\t%d0, %d1"
6536 [(set_attr "type" "fmov")
6537 (set_attr "length" "4")
6538 ])
6539
6540 ;; There is a deliberate reason why the parameters of high and lo_sum's
6541 ;; don't have modes for ADRP and ADD instructions. This is to allow high
6542 ;; and lo_sum's to be used with the labels defining the jump tables in
6543 ;; rodata section.
6544
6545 (define_expand "add_losym"
6546 [(set (match_operand 0 "register_operand")
6547 (lo_sum (match_operand 1 "register_operand")
6548 (match_operand 2 "aarch64_valid_symref")))]
6549 ""
6550 {
6551 machine_mode mode = GET_MODE (operands[0]);
6552
6553 emit_insn ((mode == DImode
6554 ? gen_add_losym_di
6555 : gen_add_losym_si) (operands[0],
6556 operands[1],
6557 operands[2]));
6558 DONE;
6559 })
6560
6561 (define_insn "add_losym_<mode>"
6562 [(set (match_operand:P 0 "register_operand" "=r")
6563 (lo_sum:P (match_operand:P 1 "register_operand" "r")
6564 (match_operand 2 "aarch64_valid_symref" "S")))]
6565 ""
6566 "add\\t%<w>0, %<w>1, :lo12:%c2"
6567 [(set_attr "type" "alu_imm")]
6568 )
6569
6570 (define_insn "ldr_got_small_<mode>"
6571 [(set (match_operand:PTR 0 "register_operand" "=r")
6572 (unspec:PTR [(mem:PTR (lo_sum:PTR
6573 (match_operand:PTR 1 "register_operand" "r")
6574 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
6575 UNSPEC_GOTSMALLPIC))]
6576 ""
6577 "ldr\\t%<w>0, [%1, #:got_lo12:%c2]"
6578 [(set_attr "type" "load_<ldst_sz>")]
6579 )
6580
6581 (define_insn "ldr_got_small_sidi"
6582 [(set (match_operand:DI 0 "register_operand" "=r")
6583 (zero_extend:DI
6584 (unspec:SI [(mem:SI (lo_sum:DI
6585 (match_operand:DI 1 "register_operand" "r")
6586 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
6587 UNSPEC_GOTSMALLPIC)))]
6588 "TARGET_ILP32"
6589 "ldr\\t%w0, [%1, #:got_lo12:%c2]"
6590 [(set_attr "type" "load_4")]
6591 )
6592
6593 (define_insn "ldr_got_small_28k_<mode>"
6594 [(set (match_operand:PTR 0 "register_operand" "=r")
6595 (unspec:PTR [(mem:PTR (lo_sum:PTR
6596 (match_operand:PTR 1 "register_operand" "r")
6597 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
6598 UNSPEC_GOTSMALLPIC28K))]
6599 ""
6600 "ldr\\t%<w>0, [%1, #:<got_modifier>:%c2]"
6601 [(set_attr "type" "load_<ldst_sz>")]
6602 )
6603
6604 (define_insn "ldr_got_small_28k_sidi"
6605 [(set (match_operand:DI 0 "register_operand" "=r")
6606 (zero_extend:DI
6607 (unspec:SI [(mem:SI (lo_sum:DI
6608 (match_operand:DI 1 "register_operand" "r")
6609 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
6610 UNSPEC_GOTSMALLPIC28K)))]
6611 "TARGET_ILP32"
6612 "ldr\\t%w0, [%1, #:gotpage_lo14:%c2]"
6613 [(set_attr "type" "load_4")]
6614 )
6615
6616 (define_insn "@ldr_got_tiny_<mode>"
6617 [(set (match_operand:PTR 0 "register_operand" "=r")
6618 (unspec:PTR [(match_operand:PTR 1 "aarch64_valid_symref" "S")]
6619 UNSPEC_GOTTINYPIC))]
6620 ""
6621 "ldr\t%<w>0, %L1"
6622 [(set_attr "type" "load_<ldst_sz>")]
6623 )
6624
6625 (define_insn "ldr_got_tiny_sidi"
6626 [(set (match_operand:DI 0 "register_operand" "=r")
6627 (zero_extend:DI
6628 (unspec:SI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
6629 UNSPEC_GOTTINYPIC)))]
6630 "TARGET_ILP32"
6631 "ldr\t%w0, %L1"
6632 [(set_attr "type" "load_4")]
6633 )
6634
6635 (define_insn "aarch64_load_tp_hard"
6636 [(set (match_operand:DI 0 "register_operand" "=r")
6637 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
6638 ""
6639 "mrs\\t%0, tpidr_el0"
6640 [(set_attr "type" "mrs")]
6641 )
6642
6643 ;; The TLS ABI specifically requires that the compiler does not schedule
6644 ;; instructions in the TLS stubs, in order to enable linker relaxation.
6645 ;; Therefore we treat the stubs as an atomic sequence.
6646 (define_expand "tlsgd_small_<mode>"
6647 [(parallel [(set (match_operand:PTR 0 "register_operand")
6648 (call (mem:DI (match_dup 2)) (const_int 1)))
6649 (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
6650 (unspec:DI [(match_operand 1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
6651 (clobber (reg:DI LR_REGNUM))])]
6652 ""
6653 {
6654 operands[2] = aarch64_tls_get_addr ();
6655 })
6656
6657 (define_insn "*tlsgd_small_<mode>"
6658 [(set (match_operand:PTR 0 "register_operand" "")
6659 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
6660 (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
6661 (unspec:DI [(match_operand 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
6662 (clobber (reg:DI LR_REGNUM))
6663 ]
6664 ""
6665 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
6666 [(set_attr "type" "call")
6667 (set_attr "length" "16")])
6668
6669 (define_insn "tlsie_small_<mode>"
6670 [(set (match_operand:PTR 0 "register_operand" "=r")
6671 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
6672 UNSPEC_GOTSMALLTLS))]
6673 ""
6674 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
6675 [(set_attr "type" "load_4")
6676 (set_attr "length" "8")]
6677 )
6678
6679 (define_insn "tlsie_small_sidi"
6680 [(set (match_operand:DI 0 "register_operand" "=r")
6681 (zero_extend:DI
6682 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
6683 UNSPEC_GOTSMALLTLS)))]
6684 ""
6685 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
6686 [(set_attr "type" "load_4")
6687 (set_attr "length" "8")]
6688 )
6689
6690 (define_insn "tlsie_tiny_<mode>"
6691 [(set (match_operand:PTR 0 "register_operand" "=&r")
6692 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
6693 (match_operand:PTR 2 "register_operand" "r")]
6694 UNSPEC_GOTTINYTLS))]
6695 ""
6696 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
6697 [(set_attr "type" "multiple")
6698 (set_attr "length" "8")]
6699 )
6700
6701 (define_insn "tlsie_tiny_sidi"
6702 [(set (match_operand:DI 0 "register_operand" "=&r")
6703 (zero_extend:DI
6704 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
6705 (match_operand:DI 2 "register_operand" "r")
6706 ]
6707 UNSPEC_GOTTINYTLS)))]
6708 ""
6709 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
6710 [(set_attr "type" "multiple")
6711 (set_attr "length" "8")]
6712 )
6713
6714 (define_insn "tlsle12_<mode>"
6715 [(set (match_operand:P 0 "register_operand" "=r")
6716 (unspec:P [(match_operand:P 1 "register_operand" "r")
6717 (match_operand 2 "aarch64_tls_le_symref" "S")]
6718 UNSPEC_TLSLE12))]
6719 ""
6720 "add\\t%<w>0, %<w>1, #%L2";
6721 [(set_attr "type" "alu_sreg")
6722 (set_attr "length" "4")]
6723 )
6724
6725 (define_insn "tlsle24_<mode>"
6726 [(set (match_operand:P 0 "register_operand" "=r")
6727 (unspec:P [(match_operand:P 1 "register_operand" "r")
6728 (match_operand 2 "aarch64_tls_le_symref" "S")]
6729 UNSPEC_TLSLE24))]
6730 ""
6731 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
6732 [(set_attr "type" "multiple")
6733 (set_attr "length" "8")]
6734 )
6735
6736 (define_insn "tlsle32_<mode>"
6737 [(set (match_operand:P 0 "register_operand" "=r")
6738 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
6739 UNSPEC_TLSLE32))]
6740 ""
6741 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
6742 [(set_attr "type" "multiple")
6743 (set_attr "length" "8")]
6744 )
6745
6746 (define_insn "tlsle48_<mode>"
6747 [(set (match_operand:P 0 "register_operand" "=r")
6748 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
6749 UNSPEC_TLSLE48))]
6750 ""
6751 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
6752 [(set_attr "type" "multiple")
6753 (set_attr "length" "12")]
6754 )
6755
6756 (define_expand "tlsdesc_small_<mode>"
6757 [(unspec:PTR [(match_operand 0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
6758 "TARGET_TLS_DESC"
6759 {
6760 if (TARGET_SVE)
6761 {
6762 rtx abi = gen_int_mode (aarch64_tlsdesc_abi_id (), DImode);
6763 rtx_insn *call
6764 = emit_call_insn (gen_tlsdesc_small_sve_<mode> (operands[0], abi));
6765 RTL_CONST_CALL_P (call) = 1;
6766 }
6767 else
6768 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
6769 DONE;
6770 }
6771 )
6772
6773 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
6774 ;; R0 and LR.
6775 (define_insn "tlsdesc_small_advsimd_<mode>"
6776 [(set (reg:PTR R0_REGNUM)
6777 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
6778 UNSPEC_TLSDESC))
6779 (clobber (reg:DI LR_REGNUM))
6780 (clobber (reg:CC CC_REGNUM))
6781 (clobber (match_scratch:DI 1 "=r"))
6782 (use (reg:DI FP_REGNUM))]
6783 "TARGET_TLS_DESC && !TARGET_SVE"
6784 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
6785 [(set_attr "type" "call")
6786 (set_attr "length" "16")])
6787
6788 ;; For SVE, model tlsdesc calls as normal calls, with the callee ABI
6789 ;; describing the extra call-preserved guarantees. This would work
6790 ;; for non-SVE too, but avoiding a call is probably better if we can.
6791 (define_insn "tlsdesc_small_sve_<mode>"
6792 [(set (reg:PTR R0_REGNUM)
6793 (call (mem:DI (unspec:PTR
6794 [(match_operand 0 "aarch64_valid_symref")]
6795 UNSPEC_TLSDESC))
6796 (const_int 0)))
6797 (unspec:DI [(match_operand:DI 1 "const_int_operand")] UNSPEC_CALLEE_ABI)
6798 (clobber (reg:DI LR_REGNUM))
6799 (clobber (match_scratch:DI 2 "=r"))]
6800 "TARGET_TLS_DESC && TARGET_SVE"
6801 "adrp\\tx0, %A0\;ldr\\t%<w>2, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%2"
6802 [(set_attr "type" "call")
6803 (set_attr "length" "16")])
6804
6805 (define_insn "stack_tie"
6806 [(set (mem:BLK (scratch))
6807 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
6808 (match_operand:DI 1 "register_operand" "rk")]
6809 UNSPEC_PRLG_STK))]
6810 ""
6811 ""
6812 [(set_attr "length" "0")]
6813 )
6814
6815 (define_insn "aarch64_fjcvtzs"
6816 [(set (match_operand:SI 0 "register_operand" "=r")
6817 (unspec:SI [(match_operand:DF 1 "register_operand" "w")]
6818 UNSPEC_FJCVTZS))
6819 (clobber (reg:CC CC_REGNUM))]
6820 "TARGET_JSCVT"
6821 "fjcvtzs\\t%w0, %d1"
6822 [(set_attr "type" "f_cvtf2i")]
6823 )
6824
6825 ;; Pointer authentication patterns are always provided. In architecture
6826 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
6827 ;; This lets the user write portable software which authenticates pointers
6828 ;; when run on something which implements ARMv8.3-A, and which runs
6829 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
6830 ;; implemented.
6831
6832 ;; Signing/Authenticating R30 using SP as the salt.
6833
6834 (define_insn "<pauth_mnem_prefix>sp"
6835 [(set (reg:DI R30_REGNUM)
6836 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
6837 ""
6838 "hint\t<pauth_hint_num> // <pauth_mnem_prefix>sp";
6839 )
6840
6841 ;; Signing/Authenticating X17 using X16 as the salt.
6842
6843 (define_insn "<pauth_mnem_prefix>1716"
6844 [(set (reg:DI R17_REGNUM)
6845 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
6846 ""
6847 "hint\t<pauth_hint_num> // <pauth_mnem_prefix>1716";
6848 )
6849
6850 ;; Stripping the signature in R30.
6851
6852 (define_insn "xpaclri"
6853 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
6854 ""
6855 "hint\t7 // xpaclri"
6856 )
6857
6858 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6859 ;; all of memory. This blocks insns from being moved across this point.
6860
6861 (define_insn "blockage"
6862 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
6863 ""
6864 ""
6865 [(set_attr "length" "0")
6866 (set_attr "type" "block")]
6867 )
6868
6869 (define_insn "probe_stack_range"
6870 [(set (match_operand:DI 0 "register_operand" "=rk")
6871 (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
6872 (match_operand:DI 2 "register_operand" "r")]
6873 UNSPECV_PROBE_STACK_RANGE))]
6874 ""
6875 {
6876 return aarch64_output_probe_stack_range (operands[0], operands[2]);
6877 }
6878 [(set_attr "length" "32")]
6879 )
6880
6881 ;; This instruction is used to generate the stack clash stack adjustment and
6882 ;; probing loop. We can't change the control flow during prologue and epilogue
6883 ;; code generation. So we must emit a volatile unspec and expand it later on.
6884
6885 (define_insn "@probe_sve_stack_clash_<mode>"
6886 [(set (match_operand:P 0 "register_operand" "=rk")
6887 (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
6888 (match_operand:P 2 "register_operand" "r")
6889 (match_operand:P 3 "const_int_operand" "n")
6890 (match_operand:P 4 "aarch64_plus_immediate" "L")]
6891 UNSPECV_PROBE_STACK_RANGE))]
6892 "TARGET_SVE"
6893 {
6894 return aarch64_output_probe_sve_stack_clash (operands[0], operands[2],
6895 operands[3], operands[4]);
6896 }
6897 [(set_attr "length" "28")]
6898 )
6899
6900 ;; Named pattern for expanding thread pointer reference.
6901 (define_expand "get_thread_pointerdi"
6902 [(match_operand:DI 0 "register_operand")]
6903 ""
6904 {
6905 rtx tmp = aarch64_load_tp (operands[0]);
6906 if (tmp != operands[0])
6907 emit_move_insn (operands[0], tmp);
6908 DONE;
6909 })
6910
6911 ;; Defined for -mstack-protector-guard=sysreg, which goes through this
6912 ;; pattern rather than stack_protect_combined_set. Our implementation
6913 ;; of the latter can handle both.
6914 (define_expand "stack_protect_set"
6915 [(match_operand 0 "memory_operand")
6916 (match_operand 1 "")]
6917 ""
6918 {
6919 emit_insn (gen_stack_protect_combined_set (operands[0], operands[1]));
6920 DONE;
6921 })
6922
6923 (define_expand "stack_protect_combined_set"
6924 [(match_operand 0 "memory_operand")
6925 (match_operand 1 "")]
6926 ""
6927 {
6928 machine_mode mode = GET_MODE (operands[0]);
6929 operands[1] = aarch64_stack_protect_canary_mem (mode, operands[1],
6930 AARCH64_SALT_SSP_SET);
6931 emit_insn ((mode == DImode
6932 ? gen_stack_protect_set_di
6933 : gen_stack_protect_set_si) (operands[0], operands[1]));
6934 DONE;
6935 })
6936
6937 ;; Operand 1 is either AARCH64_SALT_SSP_SET or AARCH64_SALT_SSP_TEST.
6938 (define_insn "reg_stack_protect_address_<mode>"
6939 [(set (match_operand:PTR 0 "register_operand" "=r")
6940 (unspec:PTR [(match_operand 1 "const_int_operand")]
6941 UNSPEC_SSP_SYSREG))]
6942 "aarch64_stack_protector_guard != SSP_GLOBAL"
6943 {
6944 char buf[150];
6945 snprintf (buf, 150, "mrs\\t%%<w>0, %s",
6946 aarch64_stack_protector_guard_reg_str);
6947 output_asm_insn (buf, operands);
6948 return "";
6949 }
6950 [(set_attr "type" "mrs")])
6951
6952 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
6953 ;; canary value does not live beyond the life of this sequence.
6954 (define_insn "stack_protect_set_<mode>"
6955 [(set (match_operand:PTR 0 "memory_operand" "=m")
6956 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
6957 UNSPEC_SP_SET))
6958 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
6959 ""
6960 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2, 0"
6961 [(set_attr "length" "12")
6962 (set_attr "type" "multiple")])
6963
6964 ;; Defined for -mstack-protector-guard=sysreg, which goes through this
6965 ;; pattern rather than stack_protect_combined_test. Our implementation
6966 ;; of the latter can handle both.
6967 (define_expand "stack_protect_test"
6968 [(match_operand 0 "memory_operand")
6969 (match_operand 1 "")
6970 (match_operand 2)]
6971 ""
6972 {
6973 emit_insn (gen_stack_protect_combined_test (operands[0], operands[1],
6974 operands[2]));
6975 DONE;
6976 })
6977
6978 (define_expand "stack_protect_combined_test"
6979 [(match_operand 0 "memory_operand")
6980 (match_operand 1 "")
6981 (match_operand 2)]
6982 ""
6983 {
6984 machine_mode mode = GET_MODE (operands[0]);
6985 operands[1] = aarch64_stack_protect_canary_mem (mode, operands[1],
6986 AARCH64_SALT_SSP_TEST);
6987 emit_insn ((mode == DImode
6988 ? gen_stack_protect_test_di
6989 : gen_stack_protect_test_si) (operands[0], operands[1]));
6990
6991 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
6992 emit_jump_insn (gen_condjump (gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx),
6993 cc_reg, operands[2]));
6994 DONE;
6995 })
6996
6997 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
6998 ;; canary value does not live beyond the end of this sequence.
6999 (define_insn "stack_protect_test_<mode>"
7000 [(set (reg:CC CC_REGNUM)
7001 (unspec:CC [(match_operand:PTR 0 "memory_operand" "m")
7002 (match_operand:PTR 1 "memory_operand" "m")]
7003 UNSPEC_SP_TEST))
7004 (clobber (match_scratch:PTR 2 "=&r"))
7005 (clobber (match_scratch:PTR 3 "=&r"))]
7006 ""
7007 "ldr\t%<w>2, %0\;ldr\t%<w>3, %1\;subs\t%<w>2, %<w>2, %<w>3\;mov\t%3, 0"
7008 [(set_attr "length" "16")
7009 (set_attr "type" "multiple")])
7010
7011 ;; Write into the Floating-point Status or Control Register.
7012 (define_insn "@aarch64_set_<fpscr_name><GPI:mode>"
7013 [(unspec_volatile [(match_operand:GPI 0 "register_operand" "r")] SET_FPSCR)]
7014 ""
7015 "msr\\t<fpscr_name>, %0"
7016 [(set_attr "type" "mrs")])
7017
7018 ;; Read into the Floating-point Status or Control Register.
7019 (define_insn "@aarch64_get_<fpscr_name><GPI:mode>"
7020 [(set (match_operand:GPI 0 "register_operand" "=r")
7021 (unspec_volatile:GPI [(const_int 0)] GET_FPSCR))]
7022 ""
7023 "mrs\\t%0, <fpscr_name>"
7024 [(set_attr "type" "mrs")])
7025
7026 ;; Define the subtract-one-and-jump insns so loop.c
7027 ;; knows what to generate.
7028 (define_expand "doloop_end"
7029 [(use (match_operand 0 "" "")) ; loop pseudo
7030 (use (match_operand 1 "" ""))] ; label
7031 "optimize > 0 && flag_modulo_sched"
7032 {
7033 rtx s0;
7034 rtx bcomp;
7035 rtx loc_ref;
7036 rtx cc_reg;
7037 rtx insn;
7038 rtx cmp;
7039
7040 /* Currently SMS relies on the do-loop pattern to recognize loops
7041 where (1) the control part consists of all insns defining and/or
7042 using a certain 'count' register and (2) the loop count can be
7043 adjusted by modifying this register prior to the loop.
7044 ??? The possible introduction of a new block to initialize the
7045 new IV can potentially affect branch optimizations. */
7046
7047 if (GET_MODE (operands[0]) != DImode)
7048 FAIL;
7049
7050 s0 = operands [0];
7051 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
7052
7053 cmp = XVECEXP (PATTERN (insn), 0, 0);
7054 cc_reg = SET_DEST (cmp);
7055 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
7056 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
7057 emit_jump_insn (gen_rtx_SET (pc_rtx,
7058 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
7059 loc_ref, pc_rtx)));
7060 DONE;
7061 })
7062
7063 ;; Track speculation through conditional branches. We assume that
7064 ;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
7065 (define_insn "speculation_tracker"
7066 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7067 (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand 0)]
7068 UNSPEC_SPECULATION_TRACKER))]
7069 ""
7070 {
7071 operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7072 output_asm_insn ("csel\\t%1, %1, xzr, %m0", operands);
7073 return "";
7074 }
7075 [(set_attr "type" "csel")]
7076 )
7077
7078 ;; Like speculation_tracker, but track the inverse condition.
7079 (define_insn "speculation_tracker_rev"
7080 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7081 (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand 0)]
7082 UNSPEC_SPECULATION_TRACKER_REV))]
7083 ""
7084 {
7085 operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7086 output_asm_insn ("csel\\t%1, %1, xzr, %M0", operands);
7087 return "";
7088 }
7089 [(set_attr "type" "csel")]
7090 )
7091
7092 ;; BTI <target> instructions
7093 (define_insn "bti_noarg"
7094 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_NOARG)]
7095 ""
7096 "hint\t32 // bti"
7097 [(set_attr "type" "no_insn")]
7098 )
7099
7100 (define_insn "bti_c"
7101 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_C)]
7102 ""
7103 "hint\t34 // bti c"
7104 [(set_attr "type" "no_insn")]
7105 )
7106
7107 (define_insn "bti_j"
7108 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_J)]
7109 ""
7110 "hint\t36 // bti j"
7111 [(set_attr "type" "no_insn")]
7112 )
7113
7114 (define_insn "bti_jc"
7115 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_JC)]
7116 ""
7117 "hint\t38 // bti jc"
7118 [(set_attr "type" "no_insn")]
7119 )
7120
7121 ;; Hard speculation barrier.
7122 (define_insn "speculation_barrier"
7123 [(unspec_volatile [(const_int 0)] UNSPECV_SPECULATION_BARRIER)]
7124 ""
7125 "isb\;dsb\\tsy"
7126 [(set_attr "length" "8")
7127 (set_attr "type" "block")
7128 (set_attr "speculation_barrier" "true")]
7129 )
7130
7131 ;; Support for __builtin_speculation_safe_value when we have speculation
7132 ;; tracking enabled. Use the speculation tracker to decide whether to
7133 ;; copy operand 1 to the target, or to copy the fail value (operand 2).
7134 (define_expand "@despeculate_copy<ALLI_TI:mode>"
7135 [(set (match_operand:ALLI_TI 0 "register_operand")
7136 (unspec_volatile:ALLI_TI
7137 [(match_operand:ALLI_TI 1 "register_operand")
7138 (match_operand:ALLI_TI 2 "aarch64_reg_or_zero")
7139 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7140 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7141 ""
7142 "
7143 {
7144 if (operands[2] == const0_rtx)
7145 {
7146 rtx tracker;
7147 if (<MODE>mode == TImode)
7148 tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7149 else
7150 tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
7151
7152 emit_insn (gen_despeculate_simple<mode> (operands[0], operands[1],
7153 tracker));
7154 DONE;
7155 }
7156 }
7157 "
7158 )
7159
7160 ;; Patterns to match despeculate_copy<mode>. Note that "hint 0x14" is the
7161 ;; encoding for CSDB, but will work in older versions of the assembler.
7162 (define_insn "*despeculate_copy<ALLI:mode>_insn"
7163 [(set (match_operand:ALLI 0 "register_operand" "=r")
7164 (unspec_volatile:ALLI
7165 [(match_operand:ALLI 1 "register_operand" "r")
7166 (match_operand:ALLI 2 "aarch64_reg_or_zero" "rZ")
7167 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7168 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7169 ""
7170 {
7171 operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7172 output_asm_insn ("cmp\\t%3, #0\;csel\\t%<w>0, %<w>1, %<w>2, ne\;hint\t0x14 // csdb",
7173 operands);
7174 return "";
7175 }
7176 [(set_attr "length" "12")
7177 (set_attr "type" "block")
7178 (set_attr "speculation_barrier" "true")]
7179 )
7180
7181 ;; Pattern to match despeculate_copyti
7182 (define_insn "*despeculate_copyti_insn"
7183 [(set (match_operand:TI 0 "register_operand" "=r")
7184 (unspec_volatile:TI
7185 [(match_operand:TI 1 "register_operand" "r")
7186 (match_operand:TI 2 "aarch64_reg_or_zero" "rZ")
7187 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7188 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7189 ""
7190 {
7191 operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7192 output_asm_insn
7193 ("cmp\\t%3, #0\;csel\\t%0, %1, %2, ne\;csel\\t%H0, %H1, %H2, ne\;hint\t0x14 // csdb",
7194 operands);
7195 return "";
7196 }
7197 [(set_attr "length" "16")
7198 (set_attr "type" "block")
7199 (set_attr "speculation_barrier" "true")]
7200 )
7201
7202 (define_insn "despeculate_simple<ALLI:mode>"
7203 [(set (match_operand:ALLI 0 "register_operand" "=r")
7204 (unspec_volatile:ALLI
7205 [(match_operand:ALLI 1 "register_operand" "r")
7206 (use (match_operand:ALLI 2 "register_operand" ""))]
7207 UNSPECV_SPECULATION_BARRIER))]
7208 ""
7209 "and\\t%<w>0, %<w>1, %<w>2\;hint\t0x14 // csdb"
7210 [(set_attr "type" "block")
7211 (set_attr "length" "8")
7212 (set_attr "speculation_barrier" "true")]
7213 )
7214
7215 (define_insn "despeculate_simpleti"
7216 [(set (match_operand:TI 0 "register_operand" "=r")
7217 (unspec_volatile:TI
7218 [(match_operand:TI 1 "register_operand" "r")
7219 (use (match_operand:DI 2 "register_operand" ""))]
7220 UNSPECV_SPECULATION_BARRIER))]
7221 ""
7222 "and\\t%0, %1, %2\;and\\t%H0, %H1, %2\;hint\t0x14 // csdb"
7223 [(set_attr "type" "block")
7224 (set_attr "length" "12")
7225 (set_attr "speculation_barrier" "true")]
7226 )
7227
7228 (define_insn "aarch64_<frintnzs_op><mode>"
7229 [(set (match_operand:VSFDF 0 "register_operand" "=w")
7230 (unspec:VSFDF [(match_operand:VSFDF 1 "register_operand" "w")]
7231 FRINTNZX))]
7232 "TARGET_FRINT && TARGET_FLOAT
7233 && !(VECTOR_MODE_P (<MODE>mode) && !TARGET_SIMD)"
7234 "<frintnzs_op>\\t%<v>0<Vmtype>, %<v>1<Vmtype>"
7235 [(set_attr "type" "f_rint<stype>")]
7236 )
7237
7238 ;; Transactional Memory Extension (TME) instructions.
7239
7240 (define_insn "tstart"
7241 [(set (match_operand:DI 0 "register_operand" "=r")
7242 (unspec_volatile:DI [(const_int 0)] UNSPECV_TSTART))
7243 (clobber (mem:BLK (scratch)))]
7244 "TARGET_TME"
7245 "tstart\\t%0"
7246 [(set_attr "type" "tme")]
7247 )
7248
7249 (define_insn "ttest"
7250 [(set (match_operand:DI 0 "register_operand" "=r")
7251 (unspec_volatile:DI [(const_int 0)] UNSPEC_TTEST))
7252 (clobber (mem:BLK (scratch)))]
7253 "TARGET_TME"
7254 "ttest\\t%0"
7255 [(set_attr "type" "tme")]
7256 )
7257
7258 (define_insn "tcommit"
7259 [(unspec_volatile:BLK [(const_int 0)] UNSPECV_TCOMMIT)
7260 (clobber (mem:BLK (scratch)))]
7261 "TARGET_TME"
7262 "tcommit"
7263 [(set_attr "type" "tme")]
7264 )
7265
7266 (define_insn "tcancel"
7267 [(unspec_volatile:BLK
7268 [(match_operand 0 "const_int_operand" "n")] UNSPECV_TCANCEL)
7269 (clobber (mem:BLK (scratch)))]
7270 "TARGET_TME && (UINTVAL (operands[0]) <= 65535)"
7271 "tcancel\\t#%0"
7272 [(set_attr "type" "tme")]
7273 )
7274
7275 (define_insn "aarch64_rndr"
7276 [(set (match_operand:DI 0 "register_operand" "=r")
7277 (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDR))
7278 (set (reg:CC_Z CC_REGNUM)
7279 (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDR))]
7280 "TARGET_RNG"
7281 "mrs\t%0, RNDR"
7282 [(set_attr "type" "mrs")]
7283 )
7284
7285 (define_insn "aarch64_rndrrs"
7286 [(set (match_operand:DI 0 "register_operand" "=r")
7287 (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDRRS))
7288 (set (reg:CC_Z CC_REGNUM)
7289 (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDRRS))]
7290 "TARGET_RNG"
7291 "mrs\t%0, RNDRRS"
7292 [(set_attr "type" "mrs")]
7293 )
7294
7295 ;; Memory Tagging Extension (MTE) instructions.
7296
7297 (define_insn "irg"
7298 [(set (match_operand:DI 0 "register_operand" "=rk")
7299 (ior:DI
7300 (and:DI (match_operand:DI 1 "register_operand" "rk")
7301 (const_int -1080863910568919041)) ;; 0xf0ff...
7302 (ashift:DI (unspec:QI [(match_operand:DI 2 "register_operand" "r")]
7303 UNSPEC_GEN_TAG_RND)
7304 (const_int 56))))]
7305 "TARGET_MEMTAG"
7306 "irg\\t%0, %1, %2"
7307 [(set_attr "type" "memtag")]
7308 )
7309
7310 (define_insn "gmi"
7311 [(set (match_operand:DI 0 "register_operand" "=r")
7312 (ior:DI (ashift:DI
7313 (const_int 1)
7314 (and:QI (lshiftrt:DI
7315 (match_operand:DI 1 "register_operand" "rk")
7316 (const_int 56)) (const_int 15)))
7317 (match_operand:DI 2 "register_operand" "r")))]
7318 "TARGET_MEMTAG"
7319 "gmi\\t%0, %1, %2"
7320 [(set_attr "type" "memtag")]
7321 )
7322
7323 (define_insn "addg"
7324 [(set (match_operand:DI 0 "register_operand" "=rk")
7325 (ior:DI
7326 (and:DI (plus:DI (match_operand:DI 1 "register_operand" "rk")
7327 (match_operand:DI 2 "aarch64_granule16_uimm6" "i"))
7328 (const_int -1080863910568919041)) ;; 0xf0ff...
7329 (ashift:DI
7330 (unspec:QI
7331 [(and:QI (lshiftrt:DI (match_dup 1) (const_int 56)) (const_int 15))
7332 (match_operand:QI 3 "aarch64_memtag_tag_offset" "i")]
7333 UNSPEC_GEN_TAG)
7334 (const_int 56))))]
7335 "TARGET_MEMTAG"
7336 "addg\\t%0, %1, #%2, #%3"
7337 [(set_attr "type" "memtag")]
7338 )
7339
7340 (define_insn "subp"
7341 [(set (match_operand:DI 0 "register_operand" "=r")
7342 (minus:DI
7343 (and:DI (match_operand:DI 1 "register_operand" "rk")
7344 (const_int 72057594037927935)) ;; 0x00ff...
7345 (and:DI (match_operand:DI 2 "register_operand" "rk")
7346 (const_int 72057594037927935))))] ;; 0x00ff...
7347 "TARGET_MEMTAG"
7348 "subp\\t%0, %1, %2"
7349 [(set_attr "type" "memtag")]
7350 )
7351
7352 ;; LDG will use the 16-byte aligned value of the address.
7353 (define_insn "ldg"
7354 [(set (match_operand:DI 0 "register_operand" "+r")
7355 (ior:DI
7356 (and:DI (match_dup 0) (const_int -1080863910568919041)) ;; 0xf0ff...
7357 (ashift:DI
7358 (mem:QI (unspec:DI
7359 [(and:DI (plus:DI (match_operand:DI 1 "register_operand" "rk")
7360 (match_operand:DI 2 "aarch64_granule16_simm9" "i"))
7361 (const_int -16))] UNSPEC_TAG_SPACE))
7362 (const_int 56))))]
7363 "TARGET_MEMTAG"
7364 "ldg\\t%0, [%1, #%2]"
7365 [(set_attr "type" "memtag")]
7366 )
7367
7368 ;; STG doesn't align the address but aborts with alignment fault
7369 ;; when the address is not 16-byte aligned.
7370 (define_insn "stg"
7371 [(set (mem:QI (unspec:DI
7372 [(plus:DI (match_operand:DI 1 "register_operand" "rk")
7373 (match_operand:DI 2 "aarch64_granule16_simm9" "i"))]
7374 UNSPEC_TAG_SPACE))
7375 (and:QI (lshiftrt:DI (match_operand:DI 0 "register_operand" "rk")
7376 (const_int 56)) (const_int 15)))]
7377 "TARGET_MEMTAG"
7378 "stg\\t%0, [%1, #%2]"
7379 [(set_attr "type" "memtag")]
7380 )
7381
7382 ;; AdvSIMD Stuff
7383 (include "aarch64-simd.md")
7384
7385 ;; Atomic Operations
7386 (include "atomics.md")
7387
7388 ;; ldp/stp peephole patterns
7389 (include "aarch64-ldpstp.md")
7390
7391 ;; SVE.
7392 (include "aarch64-sve.md")
7393
7394 ;; SVE2.
7395 (include "aarch64-sve2.md")