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