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