aarch64.md (define_attr "sync_*"): Remove.
[gcc.git] / gcc / config / aarch64 / aarch64.md
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11 ;;
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
16 ;;
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
20
21 ;; Register numbers
22 (define_constants
23 [
24 (R0_REGNUM 0)
25 (R1_REGNUM 1)
26 (R2_REGNUM 2)
27 (R3_REGNUM 3)
28 (R4_REGNUM 4)
29 (R5_REGNUM 5)
30 (R6_REGNUM 6)
31 (R7_REGNUM 7)
32 (R8_REGNUM 8)
33 (R9_REGNUM 9)
34 (R10_REGNUM 10)
35 (R11_REGNUM 11)
36 (R12_REGNUM 12)
37 (R13_REGNUM 13)
38 (R14_REGNUM 14)
39 (R15_REGNUM 15)
40 (R16_REGNUM 16)
41 (IP0_REGNUM 16)
42 (R17_REGNUM 17)
43 (IP1_REGNUM 17)
44 (R18_REGNUM 18)
45 (R19_REGNUM 19)
46 (R20_REGNUM 20)
47 (R21_REGNUM 21)
48 (R22_REGNUM 22)
49 (R23_REGNUM 23)
50 (R24_REGNUM 24)
51 (R25_REGNUM 25)
52 (R26_REGNUM 26)
53 (R27_REGNUM 27)
54 (R28_REGNUM 28)
55 (R29_REGNUM 29)
56 (R30_REGNUM 30)
57 (LR_REGNUM 30)
58 (SP_REGNUM 31)
59 (V0_REGNUM 32)
60 (V15_REGNUM 47)
61 (V31_REGNUM 63)
62 (SFP_REGNUM 64)
63 (AP_REGNUM 65)
64 (CC_REGNUM 66)
65 ]
66 )
67
68 (define_c_enum "unspec" [
69 UNSPEC_CASESI
70 UNSPEC_CLS
71 UNSPEC_FRINTA
72 UNSPEC_FRINTI
73 UNSPEC_FRINTM
74 UNSPEC_FRINTP
75 UNSPEC_FRINTX
76 UNSPEC_FRINTZ
77 UNSPEC_GOTSMALLPIC
78 UNSPEC_GOTSMALLTLS
79 UNSPEC_LD2
80 UNSPEC_LD3
81 UNSPEC_LD4
82 UNSPEC_MB
83 UNSPEC_NOP
84 UNSPEC_PRLG_STK
85 UNSPEC_RBIT
86 UNSPEC_ST2
87 UNSPEC_ST3
88 UNSPEC_ST4
89 UNSPEC_TLS
90 UNSPEC_TLSDESC
91 UNSPEC_VSTRUCTDUMMY
92 ])
93
94 (define_c_enum "unspecv" [
95 UNSPECV_EH_RETURN ; Represent EH_RETURN
96 ]
97 )
98
99 ;; If further include files are added the defintion of MD_INCLUDES
100 ;; must be updated.
101
102 (include "constraints.md")
103 (include "predicates.md")
104 (include "iterators.md")
105
106 ;; -------------------------------------------------------------------
107 ;; Instruction types and attributes
108 ;; -------------------------------------------------------------------
109
110 ;; Main data types used by the insntructions
111
112 (define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF"
113 (const_string "unknown"))
114
115 (define_attr "mode2" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF"
116 (const_string "unknown"))
117
118 ; The "v8type" attribute is used to for fine grained classification of
119 ; AArch64 instructions. This table briefly explains the meaning of each type.
120
121 ; adc add/subtract with carry.
122 ; adcs add/subtract with carry (setting condition flags).
123 ; adr calculate address.
124 ; alu simple alu instruction (no memory or fp regs access).
125 ; alu_ext simple alu instruction (sign/zero-extended register).
126 ; alu_shift simple alu instruction, with a source operand shifted by a constant.
127 ; alus simple alu instruction (setting condition flags).
128 ; alus_ext simple alu instruction (sign/zero-extended register, setting condition flags).
129 ; alus_shift simple alu instruction, with a source operand shifted by a constant (setting condition flags).
130 ; bfm bitfield move operation.
131 ; branch branch.
132 ; call subroutine call.
133 ; ccmp conditional compare.
134 ; clz count leading zeros/sign bits.
135 ; csel conditional select.
136 ; dmb data memory barrier.
137 ; extend sign/zero-extend (specialised bitfield move).
138 ; extr extract register-sized bitfield encoding.
139 ; fpsimd_load load single floating point / simd scalar register from memory.
140 ; fpsimd_load2 load pair of floating point / simd scalar registers from memory.
141 ; fpsimd_store store single floating point / simd scalar register to memory.
142 ; fpsimd_store2 store pair floating point / simd scalar registers to memory.
143 ; fadd floating point add/sub.
144 ; fccmp floating point conditional compare.
145 ; fcmp floating point comparison.
146 ; fconst floating point load immediate.
147 ; fcsel floating point conditional select.
148 ; fcvt floating point convert (float to float).
149 ; fcvtf2i floating point convert (float to integer).
150 ; fcvti2f floating point convert (integer to float).
151 ; fdiv floating point division operation.
152 ; ffarith floating point abs, neg or cpy.
153 ; fmadd floating point multiply-add/sub.
154 ; fminmax floating point min/max.
155 ; fmov floating point move (float to float).
156 ; fmovf2i floating point move (float to integer).
157 ; fmovi2f floating point move (integer to float).
158 ; fmul floating point multiply.
159 ; frint floating point round to integral.
160 ; fsqrt floating point square root.
161 ; load_acq load-acquire.
162 ; load load single general register from memory
163 ; load2 load pair of general registers from memory
164 ; logic logical operation (register).
165 ; logic_imm and/or/xor operation (immediate).
166 ; logic_shift logical operation with shift.
167 ; logics logical operation (register, setting condition flags).
168 ; logics_imm and/or/xor operation (immediate, setting condition flags).
169 ; logics_shift logical operation with shift (setting condition flags).
170 ; madd integer multiply-add/sub.
171 ; maddl widening integer multiply-add/sub.
172 ; misc miscellaneous - any type that doesn't fit into the rest.
173 ; move integer move operation.
174 ; move2 double integer move operation.
175 ; movk move 16-bit immediate with keep.
176 ; movz move 16-bit immmediate with zero/one.
177 ; mrs system/special register move.
178 ; mulh 64x64 to 128-bit multiply (high part).
179 ; mull widening multiply.
180 ; mult integer multiply instruction.
181 ; prefetch memory prefetch.
182 ; rbit reverse bits.
183 ; rev reverse bytes.
184 ; sdiv integer division operation (signed).
185 ; shift variable shift operation.
186 ; shift_imm immediate shift operation (specialised bitfield move).
187 ; store_rel store-release.
188 ; store store single general register to memory.
189 ; store2 store pair of general registers to memory.
190 ; udiv integer division operation (unsigned).
191
192 (define_attr "v8type"
193 "adc,\
194 adcs,\
195 adr,\
196 alu,\
197 alu_ext,\
198 alu_shift,\
199 alus,\
200 alus_ext,\
201 alus_shift,\
202 bfm,\
203 branch,\
204 call,\
205 ccmp,\
206 clz,\
207 csel,\
208 dmb,\
209 div,\
210 div64,\
211 extend,\
212 extr,\
213 fpsimd_load,\
214 fpsimd_load2,\
215 fpsimd_store2,\
216 fpsimd_store,\
217 fadd,\
218 fccmp,\
219 fcvt,\
220 fcvtf2i,\
221 fcvti2f,\
222 fcmp,\
223 fconst,\
224 fcsel,\
225 fdiv,\
226 ffarith,\
227 fmadd,\
228 fminmax,\
229 fmov,\
230 fmovf2i,\
231 fmovi2f,\
232 fmul,\
233 frint,\
234 fsqrt,\
235 load_acq,\
236 load1,\
237 load2,\
238 logic,\
239 logic_imm,\
240 logic_shift,\
241 logics,\
242 logics_imm,\
243 logics_shift,\
244 madd,\
245 maddl,\
246 misc,\
247 move,\
248 move2,\
249 movk,\
250 movz,\
251 mrs,\
252 mulh,\
253 mull,\
254 mult,\
255 prefetch,\
256 rbit,\
257 rev,\
258 sdiv,\
259 shift,\
260 shift_imm,\
261 store_rel,\
262 store1,\
263 store2,\
264 udiv"
265 (const_string "alu"))
266
267
268 ; The "type" attribute is used by the AArch32 backend. Below is a mapping
269 ; from "v8type" to "type".
270
271 (define_attr "type"
272 "alu,alu_shift,block,branch,call,f_2_r,f_cvt,f_flag,f_loads,
273 f_loadd,f_stored,f_stores,faddd,fadds,fcmpd,fcmps,fconstd,fconsts,
274 fcpys,fdivd,fdivs,ffarithd,ffariths,fmacd,fmacs,fmuld,fmuls,load_byte,
275 load1,load2,mult,r_2_f,store1,store2"
276 (cond [
277 (eq_attr "v8type" "alu_shift,alus_shift,logic_shift,logics_shift") (const_string "alu_shift")
278 (eq_attr "v8type" "branch") (const_string "branch")
279 (eq_attr "v8type" "call") (const_string "call")
280 (eq_attr "v8type" "fmovf2i") (const_string "f_2_r")
281 (eq_attr "v8type" "fcvt,fcvtf2i,fcvti2f") (const_string "f_cvt")
282 (and (eq_attr "v8type" "fpsimd_load") (eq_attr "mode" "SF")) (const_string "f_loads")
283 (and (eq_attr "v8type" "fpsimd_load") (eq_attr "mode" "DF")) (const_string "f_loadd")
284 (and (eq_attr "v8type" "fpsimd_store") (eq_attr "mode" "SF")) (const_string "f_stores")
285 (and (eq_attr "v8type" "fpsimd_store") (eq_attr "mode" "DF")) (const_string "f_stored")
286 (and (eq_attr "v8type" "fadd,fminmax") (eq_attr "mode" "DF")) (const_string "faddd")
287 (and (eq_attr "v8type" "fadd,fminmax") (eq_attr "mode" "SF")) (const_string "fadds")
288 (and (eq_attr "v8type" "fcmp,fccmp") (eq_attr "mode" "DF")) (const_string "fcmpd")
289 (and (eq_attr "v8type" "fcmp,fccmp") (eq_attr "mode" "SF")) (const_string "fcmps")
290 (and (eq_attr "v8type" "fconst") (eq_attr "mode" "DF")) (const_string "fconstd")
291 (and (eq_attr "v8type" "fconst") (eq_attr "mode" "SF")) (const_string "fconsts")
292 (and (eq_attr "v8type" "fdiv,fsqrt") (eq_attr "mode" "DF")) (const_string "fdivd")
293 (and (eq_attr "v8type" "fdiv,fsqrt") (eq_attr "mode" "SF")) (const_string "fdivs")
294 (and (eq_attr "v8type" "ffarith") (eq_attr "mode" "DF")) (const_string "ffarithd")
295 (and (eq_attr "v8type" "ffarith") (eq_attr "mode" "SF")) (const_string "ffariths")
296 (and (eq_attr "v8type" "fmadd") (eq_attr "mode" "DF")) (const_string "fmacd")
297 (and (eq_attr "v8type" "fmadd") (eq_attr "mode" "SF")) (const_string "fmacs")
298 (and (eq_attr "v8type" "fmul") (eq_attr "mode" "DF")) (const_string "fmuld")
299 (and (eq_attr "v8type" "fmul") (eq_attr "mode" "SF")) (const_string "fmuls")
300 (and (eq_attr "v8type" "load1") (eq_attr "mode" "QI,HI")) (const_string "load_byte")
301 (and (eq_attr "v8type" "load1") (eq_attr "mode" "SI,DI,TI")) (const_string "load1")
302 (eq_attr "v8type" "load2") (const_string "load2")
303 (and (eq_attr "v8type" "mulh,mult,mull,madd,sdiv,udiv") (eq_attr "mode" "SI")) (const_string "mult")
304 (eq_attr "v8type" "fmovi2f") (const_string "r_2_f")
305 (eq_attr "v8type" "store1") (const_string "store1")
306 (eq_attr "v8type" "store2") (const_string "store2")
307 ]
308 (const_string "alu")))
309
310 ;; Attribute that specifies whether or not the instruction touches fp
311 ;; registers.
312 (define_attr "fp" "no,yes" (const_string "no"))
313
314 ;; Attribute that specifies whether or not the instruction touches simd
315 ;; registers.
316 (define_attr "simd" "no,yes" (const_string "no"))
317
318 (define_attr "length" ""
319 (const_int 4))
320
321 ;; Attribute that controls whether an alternative is enabled or not.
322 ;; Currently it is only used to disable alternatives which touch fp or simd
323 ;; registers when -mgeneral-regs-only is specified.
324 (define_attr "enabled" "no,yes"
325 (cond [(ior
326 (and (eq_attr "fp" "yes")
327 (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
328 (and (eq_attr "simd" "yes")
329 (eq (symbol_ref "TARGET_SIMD") (const_int 0))))
330 (const_string "no")
331 ] (const_string "yes")))
332
333 ;; -------------------------------------------------------------------
334 ;; Pipeline descriptions and scheduling
335 ;; -------------------------------------------------------------------
336
337 ;; Processor types.
338 (include "aarch64-tune.md")
339
340 ;; Scheduling
341 (include "aarch64-generic.md")
342 (include "large.md")
343 (include "small.md")
344
345 ;; -------------------------------------------------------------------
346 ;; Jumps and other miscellaneous insns
347 ;; -------------------------------------------------------------------
348
349 (define_insn "indirect_jump"
350 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
351 ""
352 "br\\t%0"
353 [(set_attr "v8type" "branch")]
354 )
355
356 (define_insn "jump"
357 [(set (pc) (label_ref (match_operand 0 "" "")))]
358 ""
359 "b\\t%l0"
360 [(set_attr "v8type" "branch")]
361 )
362
363 (define_expand "cbranch<mode>4"
364 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
365 [(match_operand:GPI 1 "register_operand" "")
366 (match_operand:GPI 2 "aarch64_plus_operand" "")])
367 (label_ref (match_operand 3 "" ""))
368 (pc)))]
369 ""
370 "
371 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
372 operands[2]);
373 operands[2] = const0_rtx;
374 "
375 )
376
377 (define_expand "cbranch<mode>4"
378 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
379 [(match_operand:GPF 1 "register_operand" "")
380 (match_operand:GPF 2 "aarch64_reg_or_zero" "")])
381 (label_ref (match_operand 3 "" ""))
382 (pc)))]
383 ""
384 "
385 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
386 operands[2]);
387 operands[2] = const0_rtx;
388 "
389 )
390
391 (define_insn "*condjump"
392 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
393 [(match_operand 1 "cc_register" "") (const_int 0)])
394 (label_ref (match_operand 2 "" ""))
395 (pc)))]
396 ""
397 "b%m0\\t%l2"
398 [(set_attr "v8type" "branch")]
399 )
400
401 (define_expand "casesi"
402 [(match_operand:SI 0 "register_operand" "") ; Index
403 (match_operand:SI 1 "const_int_operand" "") ; Lower bound
404 (match_operand:SI 2 "const_int_operand" "") ; Total range
405 (match_operand:DI 3 "" "") ; Table label
406 (match_operand:DI 4 "" "")] ; Out of range label
407 ""
408 {
409 if (operands[1] != const0_rtx)
410 {
411 rtx reg = gen_reg_rtx (SImode);
412
413 /* Canonical RTL says that if you have:
414
415 (minus (X) (CONST))
416
417 then this should be emitted as:
418
419 (plus (X) (-CONST))
420
421 The use of trunc_int_for_mode ensures that the resulting
422 constant can be represented in SImode, this is important
423 for the corner case where operand[1] is INT_MIN. */
424
425 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
426
427 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
428 (operands[1], SImode))
429 operands[1] = force_reg (SImode, operands[1]);
430 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
431 operands[0] = reg;
432 }
433
434 if (!aarch64_plus_operand (operands[2], SImode))
435 operands[2] = force_reg (SImode, operands[2]);
436 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
437 const0_rtx),
438 operands[0], operands[2], operands[4]));
439
440 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
441 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
442 operands[3]));
443 DONE;
444 }
445 )
446
447 (define_insn "casesi_dispatch"
448 [(parallel
449 [(set (pc)
450 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
451 (match_operand:SI 1 "register_operand" "r")]
452 UNSPEC_CASESI)))
453 (clobber (reg:CC CC_REGNUM))
454 (clobber (match_scratch:DI 3 "=r"))
455 (clobber (match_scratch:DI 4 "=r"))
456 (use (label_ref (match_operand 2 "" "")))])]
457 ""
458 "*
459 return aarch64_output_casesi (operands);
460 "
461 [(set_attr "length" "16")
462 (set_attr "v8type" "branch")]
463 )
464
465 (define_insn "nop"
466 [(unspec[(const_int 0)] UNSPEC_NOP)]
467 ""
468 "nop"
469 [(set_attr "v8type" "misc")]
470 )
471
472 (define_expand "prologue"
473 [(clobber (const_int 0))]
474 ""
475 "
476 aarch64_expand_prologue ();
477 DONE;
478 "
479 )
480
481 (define_expand "epilogue"
482 [(clobber (const_int 0))]
483 ""
484 "
485 aarch64_expand_epilogue (false);
486 DONE;
487 "
488 )
489
490 (define_expand "sibcall_epilogue"
491 [(clobber (const_int 0))]
492 ""
493 "
494 aarch64_expand_epilogue (true);
495 DONE;
496 "
497 )
498
499 (define_insn "*do_return"
500 [(return)]
501 ""
502 "ret"
503 [(set_attr "v8type" "branch")]
504 )
505
506 (define_insn "eh_return"
507 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
508 UNSPECV_EH_RETURN)]
509 ""
510 "#"
511 [(set_attr "v8type" "branch")]
512 )
513
514 (define_split
515 [(unspec_volatile [(match_operand:DI 0 "register_operand" "")]
516 UNSPECV_EH_RETURN)]
517 "reload_completed"
518 [(set (match_dup 1) (match_dup 0))]
519 {
520 operands[1] = aarch64_final_eh_return_addr ();
521 }
522 )
523
524 (define_insn "*cb<optab><mode>1"
525 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
526 (const_int 0))
527 (label_ref (match_operand 1 "" ""))
528 (pc)))]
529 ""
530 "<cbz>\\t%<w>0, %l1"
531 [(set_attr "v8type" "branch")]
532 )
533
534 (define_insn "*tb<optab><mode>1"
535 [(set (pc) (if_then_else
536 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
537 (const_int 1)
538 (match_operand 1 "const_int_operand" "n"))
539 (const_int 0))
540 (label_ref (match_operand 2 "" ""))
541 (pc)))
542 (clobber (match_scratch:DI 3 "=r"))]
543 ""
544 "*
545 if (get_attr_length (insn) == 8)
546 return \"ubfx\\t%<w>3, %<w>0, %1, #1\;<cbz>\\t%<w>3, %l2\";
547 return \"<tbz>\\t%<w>0, %1, %l2\";
548 "
549 [(set_attr "v8type" "branch")
550 (set_attr "mode" "<MODE>")
551 (set (attr "length")
552 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
553 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
554 (const_int 4)
555 (const_int 8)))]
556 )
557
558 (define_insn "*cb<optab><mode>1"
559 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
560 (const_int 0))
561 (label_ref (match_operand 1 "" ""))
562 (pc)))
563 (clobber (match_scratch:DI 2 "=r"))]
564 ""
565 "*
566 if (get_attr_length (insn) == 8)
567 return \"ubfx\\t%<w>2, %<w>0, <sizem1>, #1\;<cbz>\\t%<w>2, %l1\";
568 return \"<tbz>\\t%<w>0, <sizem1>, %l1\";
569 "
570 [(set_attr "v8type" "branch")
571 (set_attr "mode" "<MODE>")
572 (set (attr "length")
573 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
574 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
575 (const_int 4)
576 (const_int 8)))]
577 )
578
579 ;; -------------------------------------------------------------------
580 ;; Subroutine calls and sibcalls
581 ;; -------------------------------------------------------------------
582
583 (define_expand "call"
584 [(parallel [(call (match_operand 0 "memory_operand" "")
585 (match_operand 1 "general_operand" ""))
586 (use (match_operand 2 "" ""))
587 (clobber (reg:DI LR_REGNUM))])]
588 ""
589 "
590 {
591 rtx callee;
592
593 /* In an untyped call, we can get NULL for operand 2. */
594 if (operands[2] == NULL)
595 operands[2] = const0_rtx;
596
597 /* Decide if we should generate indirect calls by loading the
598 64-bit address of the callee into a register before performing
599 the branch-and-link. */
600 callee = XEXP (operands[0], 0);
601 if (GET_CODE (callee) == SYMBOL_REF
602 ? aarch64_is_long_call_p (callee)
603 : !REG_P (callee))
604 XEXP (operands[0], 0) = force_reg (Pmode, callee);
605 }"
606 )
607
608 (define_insn "*call_reg"
609 [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
610 (match_operand 1 "" ""))
611 (use (match_operand 2 "" ""))
612 (clobber (reg:DI LR_REGNUM))]
613 ""
614 "blr\\t%0"
615 [(set_attr "v8type" "call")]
616 )
617
618 (define_insn "*call_symbol"
619 [(call (mem:DI (match_operand:DI 0 "" ""))
620 (match_operand 1 "" ""))
621 (use (match_operand 2 "" ""))
622 (clobber (reg:DI LR_REGNUM))]
623 "GET_CODE (operands[0]) == SYMBOL_REF
624 && !aarch64_is_long_call_p (operands[0])"
625 "bl\\t%a0"
626 [(set_attr "v8type" "call")]
627 )
628
629 (define_expand "call_value"
630 [(parallel [(set (match_operand 0 "" "")
631 (call (match_operand 1 "memory_operand" "")
632 (match_operand 2 "general_operand" "")))
633 (use (match_operand 3 "" ""))
634 (clobber (reg:DI LR_REGNUM))])]
635 ""
636 "
637 {
638 rtx callee;
639
640 /* In an untyped call, we can get NULL for operand 3. */
641 if (operands[3] == NULL)
642 operands[3] = const0_rtx;
643
644 /* Decide if we should generate indirect calls by loading the
645 64-bit address of the callee into a register before performing
646 the branch-and-link. */
647 callee = XEXP (operands[1], 0);
648 if (GET_CODE (callee) == SYMBOL_REF
649 ? aarch64_is_long_call_p (callee)
650 : !REG_P (callee))
651 XEXP (operands[1], 0) = force_reg (Pmode, callee);
652 }"
653 )
654
655 (define_insn "*call_value_reg"
656 [(set (match_operand 0 "" "")
657 (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
658 (match_operand 2 "" "")))
659 (use (match_operand 3 "" ""))
660 (clobber (reg:DI LR_REGNUM))]
661 ""
662 "blr\\t%1"
663 [(set_attr "v8type" "call")]
664 )
665
666 (define_insn "*call_value_symbol"
667 [(set (match_operand 0 "" "")
668 (call (mem:DI (match_operand:DI 1 "" ""))
669 (match_operand 2 "" "")))
670 (use (match_operand 3 "" ""))
671 (clobber (reg:DI LR_REGNUM))]
672 "GET_CODE (operands[1]) == SYMBOL_REF
673 && !aarch64_is_long_call_p (operands[1])"
674 "bl\\t%a1"
675 [(set_attr "v8type" "call")]
676 )
677
678 (define_expand "sibcall"
679 [(parallel [(call (match_operand 0 "memory_operand" "")
680 (match_operand 1 "general_operand" ""))
681 (return)
682 (use (match_operand 2 "" ""))])]
683 ""
684 {
685 if (operands[2] == NULL_RTX)
686 operands[2] = const0_rtx;
687 }
688 )
689
690 (define_expand "sibcall_value"
691 [(parallel [(set (match_operand 0 "" "")
692 (call (match_operand 1 "memory_operand" "")
693 (match_operand 2 "general_operand" "")))
694 (return)
695 (use (match_operand 3 "" ""))])]
696 ""
697 {
698 if (operands[3] == NULL_RTX)
699 operands[3] = const0_rtx;
700 }
701 )
702
703 (define_insn "*sibcall_insn"
704 [(call (mem:DI (match_operand:DI 0 "" "X"))
705 (match_operand 1 "" ""))
706 (return)
707 (use (match_operand 2 "" ""))]
708 "GET_CODE (operands[0]) == SYMBOL_REF"
709 "b\\t%a0"
710 [(set_attr "v8type" "branch")]
711 )
712
713 (define_insn "*sibcall_value_insn"
714 [(set (match_operand 0 "" "")
715 (call (mem:DI (match_operand 1 "" "X"))
716 (match_operand 2 "" "")))
717 (return)
718 (use (match_operand 3 "" ""))]
719 "GET_CODE (operands[1]) == SYMBOL_REF"
720 "b\\t%a1"
721 [(set_attr "v8type" "branch")]
722 )
723
724 ;; Call subroutine returning any type.
725
726 (define_expand "untyped_call"
727 [(parallel [(call (match_operand 0 "")
728 (const_int 0))
729 (match_operand 1 "")
730 (match_operand 2 "")])]
731 ""
732 {
733 int i;
734
735 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
736
737 for (i = 0; i < XVECLEN (operands[2], 0); i++)
738 {
739 rtx set = XVECEXP (operands[2], 0, i);
740 emit_move_insn (SET_DEST (set), SET_SRC (set));
741 }
742
743 /* The optimizer does not know that the call sets the function value
744 registers we stored in the result block. We avoid problems by
745 claiming that all hard registers are used and clobbered at this
746 point. */
747 emit_insn (gen_blockage ());
748 DONE;
749 })
750
751 ;; -------------------------------------------------------------------
752 ;; Moves
753 ;; -------------------------------------------------------------------
754
755 (define_expand "mov<mode>"
756 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
757 (match_operand:SHORT 1 "general_operand" ""))]
758 ""
759 "
760 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
761 operands[1] = force_reg (<MODE>mode, operands[1]);
762 "
763 )
764
765 (define_insn "*mov<mode>_aarch64"
766 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,r,m, r,*w")
767 (match_operand:SHORT 1 "general_operand" " r,M,m,rZ,*w,r"))]
768 "(register_operand (operands[0], <MODE>mode)
769 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
770 "@
771 mov\\t%w0, %w1
772 mov\\t%w0, %1
773 ldr<size>\\t%w0, %1
774 str<size>\\t%w1, %0
775 umov\\t%w0, %1.<v>[0]
776 dup\\t%0.<Vallxd>, %w1"
777 [(set_attr "v8type" "move,alu,load1,store1,*,*")
778 (set_attr "simd_type" "*,*,*,*,simd_movgp,simd_dupgp")
779 (set_attr "mode" "<MODE>")
780 (set_attr "simd_mode" "<MODE>")]
781 )
782
783 (define_expand "mov<mode>"
784 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
785 (match_operand:GPI 1 "general_operand" ""))]
786 ""
787 "
788 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
789 operands[1] = force_reg (<MODE>mode, operands[1]);
790
791 if (CONSTANT_P (operands[1]))
792 {
793 aarch64_expand_mov_immediate (operands[0], operands[1]);
794 DONE;
795 }
796 "
797 )
798
799 (define_insn "*movsi_aarch64"
800 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m, *w, r,*w")
801 (match_operand:SI 1 "aarch64_mov_operand" " r,M,m,rZ,rZ,*w,*w"))]
802 "(register_operand (operands[0], SImode)
803 || aarch64_reg_or_zero (operands[1], SImode))"
804 "@
805 mov\\t%w0, %w1
806 mov\\t%w0, %1
807 ldr\\t%w0, %1
808 str\\t%w1, %0
809 fmov\\t%s0, %w1
810 fmov\\t%w0, %s1
811 fmov\\t%s0, %s1"
812 [(set_attr "v8type" "move,alu,load1,store1,fmov,fmov,fmov")
813 (set_attr "mode" "SI")
814 (set_attr "fp" "*,*,*,*,yes,yes,yes")]
815 )
816
817 (define_insn "*movdi_aarch64"
818 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,m, r, r, *w, r,*w,w")
819 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,m,rZ,Usa,Ush,rZ,*w,*w,Dd"))]
820 "(register_operand (operands[0], DImode)
821 || aarch64_reg_or_zero (operands[1], DImode))"
822 "@
823 mov\\t%x0, %x1
824 mov\\t%0, %x1
825 mov\\t%x0, %1
826 mov\\t%x0, %1
827 ldr\\t%x0, %1
828 str\\t%x1, %0
829 adr\\t%x0, %a1
830 adrp\\t%x0, %A1
831 fmov\\t%d0, %x1
832 fmov\\t%x0, %d1
833 fmov\\t%d0, %d1
834 movi\\t%d0, %1"
835 [(set_attr "v8type" "move,move,move,alu,load1,store1,adr,adr,fmov,fmov,fmov,fmov")
836 (set_attr "mode" "DI")
837 (set_attr "fp" "*,*,*,*,*,*,*,*,yes,yes,yes,yes")]
838 )
839
840 (define_insn "insv_imm<mode>"
841 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
842 (const_int 16)
843 (match_operand 1 "const_int_operand" "n"))
844 (match_operand 2 "const_int_operand" "n"))]
845 "INTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
846 && INTVAL (operands[1]) % 16 == 0
847 && INTVAL (operands[2]) <= 0xffff"
848 "movk\\t%<w>0, %2, lsl %1"
849 [(set_attr "v8type" "movk")
850 (set_attr "mode" "<MODE>")]
851 )
852
853 (define_expand "movti"
854 [(set (match_operand:TI 0 "nonimmediate_operand" "")
855 (match_operand:TI 1 "general_operand" ""))]
856 ""
857 "
858 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
859 operands[1] = force_reg (TImode, operands[1]);
860 "
861 )
862
863 (define_insn "*movti_aarch64"
864 [(set (match_operand:TI 0
865 "nonimmediate_operand" "=r, *w,r ,*w,r ,Ump,Ump,*w,m")
866 (match_operand:TI 1
867 "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r ,Z , m,*w"))]
868 "(register_operand (operands[0], TImode)
869 || aarch64_reg_or_zero (operands[1], TImode))"
870 "@
871 #
872 #
873 #
874 orr\\t%0.16b, %1.16b, %1.16b
875 ldp\\t%0, %H0, %1
876 stp\\t%1, %H1, %0
877 stp\\txzr, xzr, %0
878 ldr\\t%q0, %1
879 str\\t%q1, %0"
880 [(set_attr "v8type" "move2,fmovi2f,fmovf2i,*, \
881 load2,store2,store2,fpsimd_load,fpsimd_store")
882 (set_attr "simd_type" "*,*,*,simd_move,*,*,*,*,*")
883 (set_attr "mode" "DI,DI,DI,TI,DI,DI,DI,TI,TI")
884 (set_attr "length" "8,8,8,4,4,4,4,4,4")
885 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")
886 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")])
887
888 ;; Split a TImode register-register or register-immediate move into
889 ;; its component DImode pieces, taking care to handle overlapping
890 ;; source and dest registers.
891 (define_split
892 [(set (match_operand:TI 0 "register_operand" "")
893 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
894 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
895 [(const_int 0)]
896 {
897 aarch64_split_128bit_move (operands[0], operands[1]);
898 DONE;
899 })
900
901 (define_expand "mov<mode>"
902 [(set (match_operand:GPF 0 "nonimmediate_operand" "")
903 (match_operand:GPF 1 "general_operand" ""))]
904 ""
905 "
906 if (!TARGET_FLOAT)
907 {
908 sorry (\"%qs and floating point code\", \"-mgeneral-regs-only\");
909 FAIL;
910 }
911
912 if (GET_CODE (operands[0]) == MEM)
913 operands[1] = force_reg (<MODE>mode, operands[1]);
914 "
915 )
916
917 (define_insn "*movsf_aarch64"
918 [(set (match_operand:SF 0 "nonimmediate_operand" "= w,?r,w,w,m,r,m ,r")
919 (match_operand:SF 1 "general_operand" "?rY, w,w,m,w,m,rY,r"))]
920 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
921 || register_operand (operands[1], SFmode))"
922 "@
923 fmov\\t%s0, %w1
924 fmov\\t%w0, %s1
925 fmov\\t%s0, %s1
926 ldr\\t%s0, %1
927 str\\t%s1, %0
928 ldr\\t%w0, %1
929 str\\t%w1, %0
930 mov\\t%w0, %w1"
931 [(set_attr "v8type" "fmovi2f,fmovf2i,fmov,fpsimd_load,fpsimd_store,fpsimd_load,fpsimd_store,fmov")
932 (set_attr "mode" "SF")]
933 )
934
935 (define_insn "*movdf_aarch64"
936 [(set (match_operand:DF 0 "nonimmediate_operand" "= w,?r,w,w,m,r,m ,r")
937 (match_operand:DF 1 "general_operand" "?rY, w,w,m,w,m,rY,r"))]
938 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
939 || register_operand (operands[1], DFmode))"
940 "@
941 fmov\\t%d0, %x1
942 fmov\\t%x0, %d1
943 fmov\\t%d0, %d1
944 ldr\\t%d0, %1
945 str\\t%d1, %0
946 ldr\\t%x0, %1
947 str\\t%x1, %0
948 mov\\t%x0, %x1"
949 [(set_attr "v8type" "fmovi2f,fmovf2i,fmov,fpsimd_load,fpsimd_store,fpsimd_load,fpsimd_store,move")
950 (set_attr "mode" "DF")]
951 )
952
953 (define_expand "movtf"
954 [(set (match_operand:TF 0 "nonimmediate_operand" "")
955 (match_operand:TF 1 "general_operand" ""))]
956 ""
957 "
958 if (!TARGET_FLOAT)
959 {
960 sorry (\"%qs and floating point code\", \"-mgeneral-regs-only\");
961 FAIL;
962 }
963
964 if (GET_CODE (operands[0]) == MEM)
965 operands[1] = force_reg (TFmode, operands[1]);
966 "
967 )
968
969 (define_insn "*movtf_aarch64"
970 [(set (match_operand:TF 0
971 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump")
972 (match_operand:TF 1
973 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,Ump,?rY"))]
974 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
975 || register_operand (operands[1], TFmode))"
976 "@
977 orr\\t%0.16b, %1.16b, %1.16b
978 mov\\t%0, %1\;mov\\t%H0, %H1
979 fmov\\t%d0, %Q1\;fmov\\t%0.d[1], %R1
980 fmov\\t%Q0, %d1\;fmov\\t%R0, %1.d[1]
981 movi\\t%0.2d, #0
982 fmov\\t%s0, wzr
983 ldr\\t%q0, %1
984 str\\t%q1, %0
985 ldp\\t%0, %H0, %1
986 stp\\t%1, %H1, %0"
987 [(set_attr "v8type" "logic,move2,fmovi2f,fmovf2i,fconst,fconst,fpsimd_load,fpsimd_store,fpsimd_load2,fpsimd_store2")
988 (set_attr "mode" "DF,DF,DF,DF,DF,DF,TF,TF,DF,DF")
989 (set_attr "length" "4,8,8,8,4,4,4,4,4,4")
990 (set_attr "fp" "*,*,yes,yes,*,yes,yes,yes,*,*")
991 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*")]
992 )
993
994
995 ;; Operands 1 and 3 are tied together by the final condition; so we allow
996 ;; fairly lax checking on the second memory operation.
997 (define_insn "load_pair<mode>"
998 [(set (match_operand:GPI 0 "register_operand" "=r")
999 (match_operand:GPI 1 "aarch64_mem_pair_operand" "Ump"))
1000 (set (match_operand:GPI 2 "register_operand" "=r")
1001 (match_operand:GPI 3 "memory_operand" "m"))]
1002 "rtx_equal_p (XEXP (operands[3], 0),
1003 plus_constant (Pmode,
1004 XEXP (operands[1], 0),
1005 GET_MODE_SIZE (<MODE>mode)))"
1006 "ldp\\t%<w>0, %<w>2, %1"
1007 [(set_attr "v8type" "load2")
1008 (set_attr "mode" "<MODE>")]
1009 )
1010
1011 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1012 ;; fairly lax checking on the second memory operation.
1013 (define_insn "store_pair<mode>"
1014 [(set (match_operand:GPI 0 "aarch64_mem_pair_operand" "=Ump")
1015 (match_operand:GPI 1 "register_operand" "r"))
1016 (set (match_operand:GPI 2 "memory_operand" "=m")
1017 (match_operand:GPI 3 "register_operand" "r"))]
1018 "rtx_equal_p (XEXP (operands[2], 0),
1019 plus_constant (Pmode,
1020 XEXP (operands[0], 0),
1021 GET_MODE_SIZE (<MODE>mode)))"
1022 "stp\\t%<w>1, %<w>3, %0"
1023 [(set_attr "v8type" "store2")
1024 (set_attr "mode" "<MODE>")]
1025 )
1026
1027 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1028 ;; fairly lax checking on the second memory operation.
1029 (define_insn "load_pair<mode>"
1030 [(set (match_operand:GPF 0 "register_operand" "=w")
1031 (match_operand:GPF 1 "aarch64_mem_pair_operand" "Ump"))
1032 (set (match_operand:GPF 2 "register_operand" "=w")
1033 (match_operand:GPF 3 "memory_operand" "m"))]
1034 "rtx_equal_p (XEXP (operands[3], 0),
1035 plus_constant (Pmode,
1036 XEXP (operands[1], 0),
1037 GET_MODE_SIZE (<MODE>mode)))"
1038 "ldp\\t%<w>0, %<w>2, %1"
1039 [(set_attr "v8type" "fpsimd_load2")
1040 (set_attr "mode" "<MODE>")]
1041 )
1042
1043 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1044 ;; fairly lax checking on the second memory operation.
1045 (define_insn "store_pair<mode>"
1046 [(set (match_operand:GPF 0 "aarch64_mem_pair_operand" "=Ump")
1047 (match_operand:GPF 1 "register_operand" "w"))
1048 (set (match_operand:GPF 2 "memory_operand" "=m")
1049 (match_operand:GPF 3 "register_operand" "w"))]
1050 "rtx_equal_p (XEXP (operands[2], 0),
1051 plus_constant (Pmode,
1052 XEXP (operands[0], 0),
1053 GET_MODE_SIZE (<MODE>mode)))"
1054 "stp\\t%<w>1, %<w>3, %0"
1055 [(set_attr "v8type" "fpsimd_load2")
1056 (set_attr "mode" "<MODE>")]
1057 )
1058
1059 ;; Load pair with writeback. This is primarily used in function epilogues
1060 ;; when restoring [fp,lr]
1061 (define_insn "loadwb_pair<GPI:mode>_<PTR:mode>"
1062 [(parallel
1063 [(set (match_operand:PTR 0 "register_operand" "=k")
1064 (plus:PTR (match_operand:PTR 1 "register_operand" "0")
1065 (match_operand:PTR 4 "const_int_operand" "n")))
1066 (set (match_operand:GPI 2 "register_operand" "=r")
1067 (mem:GPI (plus:PTR (match_dup 1)
1068 (match_dup 4))))
1069 (set (match_operand:GPI 3 "register_operand" "=r")
1070 (mem:GPI (plus:PTR (match_dup 1)
1071 (match_operand:PTR 5 "const_int_operand" "n"))))])]
1072 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1073 "ldp\\t%<w>2, %<w>3, [%1], %4"
1074 [(set_attr "v8type" "load2")
1075 (set_attr "mode" "<GPI:MODE>")]
1076 )
1077
1078 ;; Store pair with writeback. This is primarily used in function prologues
1079 ;; when saving [fp,lr]
1080 (define_insn "storewb_pair<GPI:mode>_<PTR:mode>"
1081 [(parallel
1082 [(set (match_operand:PTR 0 "register_operand" "=&k")
1083 (plus:PTR (match_operand:PTR 1 "register_operand" "0")
1084 (match_operand:PTR 4 "const_int_operand" "n")))
1085 (set (mem:GPI (plus:PTR (match_dup 0)
1086 (match_dup 4)))
1087 (match_operand:GPI 2 "register_operand" "r"))
1088 (set (mem:GPI (plus:PTR (match_dup 0)
1089 (match_operand:PTR 5 "const_int_operand" "n")))
1090 (match_operand:GPI 3 "register_operand" "r"))])]
1091 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1092 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1093 [(set_attr "v8type" "store2")
1094 (set_attr "mode" "<GPI:MODE>")]
1095 )
1096
1097 ;; -------------------------------------------------------------------
1098 ;; Sign/Zero extension
1099 ;; -------------------------------------------------------------------
1100
1101 (define_expand "<optab>sidi2"
1102 [(set (match_operand:DI 0 "register_operand")
1103 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1104 ""
1105 )
1106
1107 (define_insn "*extendsidi2_aarch64"
1108 [(set (match_operand:DI 0 "register_operand" "=r,r")
1109 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1110 ""
1111 "@
1112 sxtw\t%0, %w1
1113 ldrsw\t%0, %1"
1114 [(set_attr "v8type" "extend,load1")
1115 (set_attr "mode" "DI")]
1116 )
1117
1118 (define_insn "*zero_extendsidi2_aarch64"
1119 [(set (match_operand:DI 0 "register_operand" "=r,r")
1120 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1121 ""
1122 "@
1123 uxtw\t%0, %w1
1124 ldr\t%w0, %1"
1125 [(set_attr "v8type" "extend,load1")
1126 (set_attr "mode" "DI")]
1127 )
1128
1129 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1130 [(set (match_operand:GPI 0 "register_operand")
1131 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1132 ""
1133 )
1134
1135 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1136 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1137 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1138 ""
1139 "@
1140 sxt<SHORT:size>\t%<GPI:w>0, %w1
1141 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1142 [(set_attr "v8type" "extend,load1")
1143 (set_attr "mode" "<GPI:MODE>")]
1144 )
1145
1146 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1147 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1148 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1149 ""
1150 "@
1151 uxt<SHORT:size>\t%<GPI:w>0, %w1
1152 ldr<SHORT:size>\t%w0, %1"
1153 [(set_attr "v8type" "extend,load1")
1154 (set_attr "mode" "<GPI:MODE>")]
1155 )
1156
1157 (define_expand "<optab>qihi2"
1158 [(set (match_operand:HI 0 "register_operand")
1159 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1160 ""
1161 )
1162
1163 (define_insn "*<optab>qihi2_aarch64"
1164 [(set (match_operand:HI 0 "register_operand" "=r,r")
1165 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1166 ""
1167 "@
1168 <su>xtb\t%w0, %w1
1169 <ldrxt>b\t%w0, %1"
1170 [(set_attr "v8type" "extend,load1")
1171 (set_attr "mode" "HI")]
1172 )
1173
1174 ;; -------------------------------------------------------------------
1175 ;; Simple arithmetic
1176 ;; -------------------------------------------------------------------
1177
1178 (define_expand "add<mode>3"
1179 [(set
1180 (match_operand:GPI 0 "register_operand" "")
1181 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1182 (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1183 ""
1184 "
1185 if (! aarch64_plus_operand (operands[2], VOIDmode))
1186 {
1187 rtx subtarget = ((optimize && can_create_pseudo_p ())
1188 ? gen_reg_rtx (<MODE>mode) : operands[0]);
1189 HOST_WIDE_INT imm = INTVAL (operands[2]);
1190
1191 if (imm < 0)
1192 imm = -(-imm & ~0xfff);
1193 else
1194 imm &= ~0xfff;
1195
1196 emit_insn (gen_add<mode>3 (subtarget, operands[1], GEN_INT (imm)));
1197 operands[1] = subtarget;
1198 operands[2] = GEN_INT (INTVAL (operands[2]) - imm);
1199 }
1200 "
1201 )
1202
1203 (define_insn "*addsi3_aarch64"
1204 [(set
1205 (match_operand:SI 0 "register_operand" "=rk,rk,rk")
1206 (plus:SI
1207 (match_operand:SI 1 "register_operand" "%rk,rk,rk")
1208 (match_operand:SI 2 "aarch64_plus_operand" "I,r,J")))]
1209 ""
1210 "@
1211 add\\t%w0, %w1, %2
1212 add\\t%w0, %w1, %w2
1213 sub\\t%w0, %w1, #%n2"
1214 [(set_attr "v8type" "alu")
1215 (set_attr "mode" "SI")]
1216 )
1217
1218 (define_insn "*adddi3_aarch64"
1219 [(set
1220 (match_operand:DI 0 "register_operand" "=rk,rk,rk,!w")
1221 (plus:DI
1222 (match_operand:DI 1 "register_operand" "%rk,rk,rk,!w")
1223 (match_operand:DI 2 "aarch64_plus_operand" "I,r,J,!w")))]
1224 ""
1225 "@
1226 add\\t%x0, %x1, %2
1227 add\\t%x0, %x1, %x2
1228 sub\\t%x0, %x1, #%n2
1229 add\\t%d0, %d1, %d2"
1230 [(set_attr "v8type" "alu")
1231 (set_attr "mode" "DI")
1232 (set_attr "simd" "*,*,*,yes")]
1233 )
1234
1235 (define_insn "*add<mode>3_compare0"
1236 [(set (reg:CC_NZ CC_REGNUM)
1237 (compare:CC_NZ
1238 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r")
1239 (match_operand:GPI 2 "aarch64_plus_operand" "rI,J"))
1240 (const_int 0)))
1241 (set (match_operand:GPI 0 "register_operand" "=r,r")
1242 (plus:GPI (match_dup 1) (match_dup 2)))]
1243 ""
1244 "@
1245 adds\\t%<w>0, %<w>1, %<w>2
1246 subs\\t%<w>0, %<w>1, #%n2"
1247 [(set_attr "v8type" "alus")
1248 (set_attr "mode" "<MODE>")]
1249 )
1250
1251 (define_insn "*add<mode>3nr_compare0"
1252 [(set (reg:CC_NZ CC_REGNUM)
1253 (compare:CC_NZ
1254 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r")
1255 (match_operand:GPI 1 "aarch64_plus_operand" "rI,J"))
1256 (const_int 0)))]
1257 ""
1258 "@
1259 cmn\\t%<w>0, %<w>1
1260 cmp\\t%<w>0, #%n1"
1261 [(set_attr "v8type" "alus")
1262 (set_attr "mode" "<MODE>")]
1263 )
1264
1265 (define_insn "*compare_neg<mode>"
1266 [(set (reg:CC CC_REGNUM)
1267 (compare:CC
1268 (match_operand:GPI 0 "register_operand" "r")
1269 (neg:GPI (match_operand:GPI 1 "register_operand" "r"))))]
1270 ""
1271 "cmn\\t%<w>0, %<w>1"
1272 [(set_attr "v8type" "alus")
1273 (set_attr "mode" "<MODE>")]
1274 )
1275
1276 (define_insn "*add_<shift>_<mode>"
1277 [(set (match_operand:GPI 0 "register_operand" "=rk")
1278 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
1279 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1280 (match_operand:GPI 3 "register_operand" "r")))]
1281 ""
1282 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1283 [(set_attr "v8type" "alu_shift")
1284 (set_attr "mode" "<MODE>")]
1285 )
1286
1287 (define_insn "*add_mul_imm_<mode>"
1288 [(set (match_operand:GPI 0 "register_operand" "=rk")
1289 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1290 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1291 (match_operand:GPI 3 "register_operand" "r")))]
1292 ""
1293 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1294 [(set_attr "v8type" "alu_shift")
1295 (set_attr "mode" "<MODE>")]
1296 )
1297
1298 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
1299 [(set (match_operand:GPI 0 "register_operand" "=rk")
1300 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1301 (match_operand:GPI 2 "register_operand" "r")))]
1302 ""
1303 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1304 [(set_attr "v8type" "alu_ext")
1305 (set_attr "mode" "<GPI:MODE>")]
1306 )
1307
1308 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
1309 [(set (match_operand:GPI 0 "register_operand" "=rk")
1310 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
1311 (match_operand:ALLX 1 "register_operand" "r"))
1312 (match_operand 2 "aarch64_imm3" "Ui3"))
1313 (match_operand:GPI 3 "register_operand" "r")))]
1314 ""
1315 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1316 [(set_attr "v8type" "alu_ext")
1317 (set_attr "mode" "<GPI:MODE>")]
1318 )
1319
1320 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
1321 [(set (match_operand:GPI 0 "register_operand" "=rk")
1322 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
1323 (match_operand:ALLX 1 "register_operand" "r"))
1324 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1325 (match_operand:GPI 3 "register_operand" "r")))]
1326 ""
1327 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
1328 [(set_attr "v8type" "alu_ext")
1329 (set_attr "mode" "<GPI:MODE>")]
1330 )
1331
1332 (define_insn "*add_<optab><mode>_multp2"
1333 [(set (match_operand:GPI 0 "register_operand" "=rk")
1334 (plus:GPI (ANY_EXTRACT:GPI
1335 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1336 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1337 (match_operand 3 "const_int_operand" "n")
1338 (const_int 0))
1339 (match_operand:GPI 4 "register_operand" "r")))]
1340 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1341 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1342 [(set_attr "v8type" "alu_ext")
1343 (set_attr "mode" "<MODE>")]
1344 )
1345
1346 (define_insn "*add<mode>3_carryin"
1347 [(set
1348 (match_operand:GPI 0 "register_operand" "=r")
1349 (plus:GPI (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1350 (plus:GPI
1351 (match_operand:GPI 1 "register_operand" "r")
1352 (match_operand:GPI 2 "register_operand" "r"))))]
1353 ""
1354 "adc\\t%<w>0, %<w>1, %<w>2"
1355 [(set_attr "v8type" "adc")
1356 (set_attr "mode" "<MODE>")]
1357 )
1358
1359 (define_insn "*add<mode>3_carryin_alt1"
1360 [(set
1361 (match_operand:GPI 0 "register_operand" "=r")
1362 (plus:GPI (plus:GPI
1363 (match_operand:GPI 1 "register_operand" "r")
1364 (match_operand:GPI 2 "register_operand" "r"))
1365 (geu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
1366 ""
1367 "adc\\t%<w>0, %<w>1, %<w>2"
1368 [(set_attr "v8type" "adc")
1369 (set_attr "mode" "<MODE>")]
1370 )
1371
1372 (define_insn "*add<mode>3_carryin_alt2"
1373 [(set
1374 (match_operand:GPI 0 "register_operand" "=r")
1375 (plus:GPI (plus:GPI
1376 (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1377 (match_operand:GPI 1 "register_operand" "r"))
1378 (match_operand:GPI 2 "register_operand" "r")))]
1379 ""
1380 "adc\\t%<w>0, %<w>1, %<w>2"
1381 [(set_attr "v8type" "adc")
1382 (set_attr "mode" "<MODE>")]
1383 )
1384
1385 (define_insn "*add<mode>3_carryin_alt3"
1386 [(set
1387 (match_operand:GPI 0 "register_operand" "=r")
1388 (plus:GPI (plus:GPI
1389 (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1390 (match_operand:GPI 2 "register_operand" "r"))
1391 (match_operand:GPI 1 "register_operand" "r")))]
1392 ""
1393 "adc\\t%<w>0, %<w>1, %<w>2"
1394 [(set_attr "v8type" "adc")
1395 (set_attr "mode" "<MODE>")]
1396 )
1397
1398 (define_insn "*add_uxt<mode>_multp2"
1399 [(set (match_operand:GPI 0 "register_operand" "=rk")
1400 (plus:GPI (and:GPI
1401 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1402 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1403 (match_operand 3 "const_int_operand" "n"))
1404 (match_operand:GPI 4 "register_operand" "r")))]
1405 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
1406 "*
1407 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1408 INTVAL (operands[3])));
1409 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
1410 [(set_attr "v8type" "alu_ext")
1411 (set_attr "mode" "<MODE>")]
1412 )
1413
1414 (define_insn "subsi3"
1415 [(set (match_operand:SI 0 "register_operand" "=rk")
1416 (minus:SI (match_operand:SI 1 "register_operand" "r")
1417 (match_operand:SI 2 "register_operand" "r")))]
1418 ""
1419 "sub\\t%w0, %w1, %w2"
1420 [(set_attr "v8type" "alu")
1421 (set_attr "mode" "SI")]
1422 )
1423
1424 (define_insn "subdi3"
1425 [(set (match_operand:DI 0 "register_operand" "=rk,!w")
1426 (minus:DI (match_operand:DI 1 "register_operand" "r,!w")
1427 (match_operand:DI 2 "register_operand" "r,!w")))]
1428 ""
1429 "@
1430 sub\\t%x0, %x1, %x2
1431 sub\\t%d0, %d1, %d2"
1432 [(set_attr "v8type" "alu")
1433 (set_attr "mode" "DI")
1434 (set_attr "simd" "*,yes")]
1435 )
1436
1437
1438 (define_insn "*sub<mode>3_compare0"
1439 [(set (reg:CC_NZ CC_REGNUM)
1440 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1441 (match_operand:GPI 2 "register_operand" "r"))
1442 (const_int 0)))
1443 (set (match_operand:GPI 0 "register_operand" "=r")
1444 (minus:GPI (match_dup 1) (match_dup 2)))]
1445 ""
1446 "subs\\t%<w>0, %<w>1, %<w>2"
1447 [(set_attr "v8type" "alus")
1448 (set_attr "mode" "<MODE>")]
1449 )
1450
1451 (define_insn "*sub_<shift>_<mode>"
1452 [(set (match_operand:GPI 0 "register_operand" "=rk")
1453 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
1454 (ASHIFT:GPI
1455 (match_operand:GPI 1 "register_operand" "r")
1456 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
1457 ""
1458 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1459 [(set_attr "v8type" "alu_shift")
1460 (set_attr "mode" "<MODE>")]
1461 )
1462
1463 (define_insn "*sub_mul_imm_<mode>"
1464 [(set (match_operand:GPI 0 "register_operand" "=rk")
1465 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
1466 (mult:GPI
1467 (match_operand:GPI 1 "register_operand" "r")
1468 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
1469 ""
1470 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1471 [(set_attr "v8type" "alu_shift")
1472 (set_attr "mode" "<MODE>")]
1473 )
1474
1475 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
1476 [(set (match_operand:GPI 0 "register_operand" "=rk")
1477 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1478 (ANY_EXTEND:GPI
1479 (match_operand:ALLX 2 "register_operand" "r"))))]
1480 ""
1481 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1482 [(set_attr "v8type" "alu_ext")
1483 (set_attr "mode" "<GPI:MODE>")]
1484 )
1485
1486 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
1487 [(set (match_operand:GPI 0 "register_operand" "=rk")
1488 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1489 (ashift:GPI (ANY_EXTEND:GPI
1490 (match_operand:ALLX 2 "register_operand" "r"))
1491 (match_operand 3 "aarch64_imm3" "Ui3"))))]
1492 ""
1493 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1494 [(set_attr "v8type" "alu_ext")
1495 (set_attr "mode" "<GPI:MODE>")]
1496 )
1497
1498 (define_insn "*sub_<optab><mode>_multp2"
1499 [(set (match_operand:GPI 0 "register_operand" "=rk")
1500 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1501 (ANY_EXTRACT:GPI
1502 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1503 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1504 (match_operand 3 "const_int_operand" "n")
1505 (const_int 0))))]
1506 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1507 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1508 [(set_attr "v8type" "alu_ext")
1509 (set_attr "mode" "<MODE>")]
1510 )
1511
1512 (define_insn "*sub_uxt<mode>_multp2"
1513 [(set (match_operand:GPI 0 "register_operand" "=rk")
1514 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1515 (and:GPI
1516 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1517 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1518 (match_operand 3 "const_int_operand" "n"))))]
1519 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
1520 "*
1521 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1522 INTVAL (operands[3])));
1523 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
1524 [(set_attr "v8type" "alu_ext")
1525 (set_attr "mode" "<MODE>")]
1526 )
1527
1528 (define_insn "neg<mode>2"
1529 [(set (match_operand:GPI 0 "register_operand" "=r")
1530 (neg:GPI (match_operand:GPI 1 "register_operand" "r")))]
1531 ""
1532 "neg\\t%<w>0, %<w>1"
1533 [(set_attr "v8type" "alu")
1534 (set_attr "mode" "<MODE>")]
1535 )
1536
1537 (define_insn "*neg<mode>2_compare0"
1538 [(set (reg:CC_NZ CC_REGNUM)
1539 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
1540 (const_int 0)))
1541 (set (match_operand:GPI 0 "register_operand" "=r")
1542 (neg:GPI (match_dup 1)))]
1543 ""
1544 "negs\\t%<w>0, %<w>1"
1545 [(set_attr "v8type" "alus")
1546 (set_attr "mode" "<MODE>")]
1547 )
1548
1549 (define_insn "*neg_<shift>_<mode>2"
1550 [(set (match_operand:GPI 0 "register_operand" "=r")
1551 (neg:GPI (ASHIFT:GPI
1552 (match_operand:GPI 1 "register_operand" "r")
1553 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
1554 ""
1555 "neg\\t%<w>0, %<w>1, <shift> %2"
1556 [(set_attr "v8type" "alu_shift")
1557 (set_attr "mode" "<MODE>")]
1558 )
1559
1560 (define_insn "*neg_mul_imm_<mode>2"
1561 [(set (match_operand:GPI 0 "register_operand" "=r")
1562 (neg:GPI (mult:GPI
1563 (match_operand:GPI 1 "register_operand" "r")
1564 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
1565 ""
1566 "neg\\t%<w>0, %<w>1, lsl %p2"
1567 [(set_attr "v8type" "alu_shift")
1568 (set_attr "mode" "<MODE>")]
1569 )
1570
1571 (define_insn "mul<mode>3"
1572 [(set (match_operand:GPI 0 "register_operand" "=r")
1573 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1574 (match_operand:GPI 2 "register_operand" "r")))]
1575 ""
1576 "mul\\t%<w>0, %<w>1, %<w>2"
1577 [(set_attr "v8type" "mult")
1578 (set_attr "mode" "<MODE>")]
1579 )
1580
1581 (define_insn "*madd<mode>"
1582 [(set (match_operand:GPI 0 "register_operand" "=r")
1583 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1584 (match_operand:GPI 2 "register_operand" "r"))
1585 (match_operand:GPI 3 "register_operand" "r")))]
1586 ""
1587 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
1588 [(set_attr "v8type" "madd")
1589 (set_attr "mode" "<MODE>")]
1590 )
1591
1592 (define_insn "*msub<mode>"
1593 [(set (match_operand:GPI 0 "register_operand" "=r")
1594 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
1595 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1596 (match_operand:GPI 2 "register_operand" "r"))))]
1597
1598 ""
1599 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
1600 [(set_attr "v8type" "madd")
1601 (set_attr "mode" "<MODE>")]
1602 )
1603
1604 (define_insn "*mul<mode>_neg"
1605 [(set (match_operand:GPI 0 "register_operand" "=r")
1606 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
1607 (match_operand:GPI 2 "register_operand" "r")))]
1608
1609 ""
1610 "mneg\\t%<w>0, %<w>1, %<w>2"
1611 [(set_attr "v8type" "mult")
1612 (set_attr "mode" "<MODE>")]
1613 )
1614
1615 (define_insn "<su_optab>mulsidi3"
1616 [(set (match_operand:DI 0 "register_operand" "=r")
1617 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
1618 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
1619 ""
1620 "<su>mull\\t%0, %w1, %w2"
1621 [(set_attr "v8type" "mull")
1622 (set_attr "mode" "DI")]
1623 )
1624
1625 (define_insn "<su_optab>maddsidi4"
1626 [(set (match_operand:DI 0 "register_operand" "=r")
1627 (plus:DI (mult:DI
1628 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
1629 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
1630 (match_operand:DI 3 "register_operand" "r")))]
1631 ""
1632 "<su>maddl\\t%0, %w1, %w2, %3"
1633 [(set_attr "v8type" "maddl")
1634 (set_attr "mode" "DI")]
1635 )
1636
1637 (define_insn "<su_optab>msubsidi4"
1638 [(set (match_operand:DI 0 "register_operand" "=r")
1639 (minus:DI
1640 (match_operand:DI 3 "register_operand" "r")
1641 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
1642 (ANY_EXTEND:DI
1643 (match_operand:SI 2 "register_operand" "r")))))]
1644 ""
1645 "<su>msubl\\t%0, %w1, %w2, %3"
1646 [(set_attr "v8type" "maddl")
1647 (set_attr "mode" "DI")]
1648 )
1649
1650 (define_insn "*<su_optab>mulsidi_neg"
1651 [(set (match_operand:DI 0 "register_operand" "=r")
1652 (mult:DI (neg:DI
1653 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
1654 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
1655 ""
1656 "<su>mnegl\\t%0, %w1, %w2"
1657 [(set_attr "v8type" "mull")
1658 (set_attr "mode" "DI")]
1659 )
1660
1661 (define_insn "<su>muldi3_highpart"
1662 [(set (match_operand:DI 0 "register_operand" "=r")
1663 (truncate:DI
1664 (lshiftrt:TI
1665 (mult:TI
1666 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
1667 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
1668 (const_int 64))))]
1669 ""
1670 "<su>mulh\\t%0, %1, %2"
1671 [(set_attr "v8type" "mulh")
1672 (set_attr "mode" "DI")]
1673 )
1674
1675 (define_insn "<su_optab>div<mode>3"
1676 [(set (match_operand:GPI 0 "register_operand" "=r")
1677 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
1678 (match_operand:GPI 2 "register_operand" "r")))]
1679 ""
1680 "<su>div\\t%<w>0, %<w>1, %<w>2"
1681 [(set_attr "v8type" "<su>div")
1682 (set_attr "mode" "<MODE>")]
1683 )
1684
1685 ;; -------------------------------------------------------------------
1686 ;; Comparison insns
1687 ;; -------------------------------------------------------------------
1688
1689 (define_insn "*cmp<mode>"
1690 [(set (reg:CC CC_REGNUM)
1691 (compare:CC (match_operand:GPI 0 "register_operand" "r,r")
1692 (match_operand:GPI 1 "aarch64_plus_operand" "rI,J")))]
1693 ""
1694 "@
1695 cmp\\t%<w>0, %<w>1
1696 cmn\\t%<w>0, #%n1"
1697 [(set_attr "v8type" "alus")
1698 (set_attr "mode" "<MODE>")]
1699 )
1700
1701 (define_insn "*cmp<mode>"
1702 [(set (reg:CCFP CC_REGNUM)
1703 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
1704 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
1705 "TARGET_FLOAT"
1706 "@
1707 fcmp\\t%<s>0, #0.0
1708 fcmp\\t%<s>0, %<s>1"
1709 [(set_attr "v8type" "fcmp")
1710 (set_attr "mode" "<MODE>")]
1711 )
1712
1713 (define_insn "*cmpe<mode>"
1714 [(set (reg:CCFPE CC_REGNUM)
1715 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
1716 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
1717 "TARGET_FLOAT"
1718 "@
1719 fcmpe\\t%<s>0, #0.0
1720 fcmpe\\t%<s>0, %<s>1"
1721 [(set_attr "v8type" "fcmp")
1722 (set_attr "mode" "<MODE>")]
1723 )
1724
1725 (define_insn "*cmp_swp_<shift>_reg<mode>"
1726 [(set (reg:CC_SWP CC_REGNUM)
1727 (compare:CC_SWP (ASHIFT:GPI
1728 (match_operand:GPI 0 "register_operand" "r")
1729 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
1730 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
1731 ""
1732 "cmp\\t%<w>2, %<w>0, <shift> %1"
1733 [(set_attr "v8type" "alus_shift")
1734 (set_attr "mode" "<MODE>")]
1735 )
1736
1737 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
1738 [(set (reg:CC_SWP CC_REGNUM)
1739 (compare:CC_SWP (ANY_EXTEND:GPI
1740 (match_operand:ALLX 0 "register_operand" "r"))
1741 (match_operand:GPI 1 "register_operand" "r")))]
1742 ""
1743 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
1744 [(set_attr "v8type" "alus_ext")
1745 (set_attr "mode" "<GPI:MODE>")]
1746 )
1747
1748
1749 ;; -------------------------------------------------------------------
1750 ;; Store-flag and conditional select insns
1751 ;; -------------------------------------------------------------------
1752
1753 (define_expand "cstore<mode>4"
1754 [(set (match_operand:SI 0 "register_operand" "")
1755 (match_operator:SI 1 "aarch64_comparison_operator"
1756 [(match_operand:GPI 2 "register_operand" "")
1757 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
1758 ""
1759 "
1760 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
1761 operands[3]);
1762 operands[3] = const0_rtx;
1763 "
1764 )
1765
1766 (define_expand "cstore<mode>4"
1767 [(set (match_operand:SI 0 "register_operand" "")
1768 (match_operator:SI 1 "aarch64_comparison_operator"
1769 [(match_operand:GPF 2 "register_operand" "")
1770 (match_operand:GPF 3 "register_operand" "")]))]
1771 ""
1772 "
1773 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
1774 operands[3]);
1775 operands[3] = const0_rtx;
1776 "
1777 )
1778
1779 (define_insn "*cstore<mode>_insn"
1780 [(set (match_operand:ALLI 0 "register_operand" "=r")
1781 (match_operator:ALLI 1 "aarch64_comparison_operator"
1782 [(match_operand 2 "cc_register" "") (const_int 0)]))]
1783 ""
1784 "cset\\t%<w>0, %m1"
1785 [(set_attr "v8type" "csel")
1786 (set_attr "mode" "<MODE>")]
1787 )
1788
1789 (define_insn "*cstore<mode>_neg"
1790 [(set (match_operand:ALLI 0 "register_operand" "=r")
1791 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator"
1792 [(match_operand 2 "cc_register" "") (const_int 0)])))]
1793 ""
1794 "csetm\\t%<w>0, %m1"
1795 [(set_attr "v8type" "csel")
1796 (set_attr "mode" "<MODE>")]
1797 )
1798
1799 (define_expand "cmov<mode>6"
1800 [(set (match_operand:GPI 0 "register_operand" "")
1801 (if_then_else:GPI
1802 (match_operator 1 "aarch64_comparison_operator"
1803 [(match_operand:GPI 2 "register_operand" "")
1804 (match_operand:GPI 3 "aarch64_plus_operand" "")])
1805 (match_operand:GPI 4 "register_operand" "")
1806 (match_operand:GPI 5 "register_operand" "")))]
1807 ""
1808 "
1809 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
1810 operands[3]);
1811 operands[3] = const0_rtx;
1812 "
1813 )
1814
1815 (define_expand "cmov<mode>6"
1816 [(set (match_operand:GPF 0 "register_operand" "")
1817 (if_then_else:GPF
1818 (match_operator 1 "aarch64_comparison_operator"
1819 [(match_operand:GPF 2 "register_operand" "")
1820 (match_operand:GPF 3 "register_operand" "")])
1821 (match_operand:GPF 4 "register_operand" "")
1822 (match_operand:GPF 5 "register_operand" "")))]
1823 ""
1824 "
1825 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
1826 operands[3]);
1827 operands[3] = const0_rtx;
1828 "
1829 )
1830
1831 (define_insn "*cmov<mode>_insn"
1832 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
1833 (if_then_else:ALLI
1834 (match_operator 1 "aarch64_comparison_operator"
1835 [(match_operand 2 "cc_register" "") (const_int 0)])
1836 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
1837 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
1838 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
1839 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
1840 ;; Final two alternatives should be unreachable, but included for completeness
1841 "@
1842 csel\\t%<w>0, %<w>3, %<w>4, %m1
1843 csinv\\t%<w>0, %<w>3, <w>zr, %m1
1844 csinv\\t%<w>0, %<w>4, <w>zr, %M1
1845 csinc\\t%<w>0, %<w>3, <w>zr, %m1
1846 csinc\\t%<w>0, %<w>4, <w>zr, %M1
1847 mov\\t%<w>0, -1
1848 mov\\t%<w>0, 1"
1849 [(set_attr "v8type" "csel")
1850 (set_attr "mode" "<MODE>")]
1851 )
1852
1853 (define_insn "*cmov<mode>_insn"
1854 [(set (match_operand:GPF 0 "register_operand" "=w")
1855 (if_then_else:GPF
1856 (match_operator 1 "aarch64_comparison_operator"
1857 [(match_operand 2 "cc_register" "") (const_int 0)])
1858 (match_operand:GPF 3 "register_operand" "w")
1859 (match_operand:GPF 4 "register_operand" "w")))]
1860 "TARGET_FLOAT"
1861 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
1862 [(set_attr "v8type" "fcsel")
1863 (set_attr "mode" "<MODE>")]
1864 )
1865
1866 (define_expand "mov<mode>cc"
1867 [(set (match_operand:ALLI 0 "register_operand" "")
1868 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
1869 (match_operand:ALLI 2 "register_operand" "")
1870 (match_operand:ALLI 3 "register_operand" "")))]
1871 ""
1872 {
1873 rtx ccreg;
1874 enum rtx_code code = GET_CODE (operands[1]);
1875
1876 if (code == UNEQ || code == LTGT)
1877 FAIL;
1878
1879 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
1880 XEXP (operands[1], 1));
1881 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
1882 }
1883 )
1884
1885 (define_expand "mov<GPF:mode><GPI:mode>cc"
1886 [(set (match_operand:GPI 0 "register_operand" "")
1887 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
1888 (match_operand:GPF 2 "register_operand" "")
1889 (match_operand:GPF 3 "register_operand" "")))]
1890 ""
1891 {
1892 rtx ccreg;
1893 enum rtx_code code = GET_CODE (operands[1]);
1894
1895 if (code == UNEQ || code == LTGT)
1896 FAIL;
1897
1898 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
1899 XEXP (operands[1], 1));
1900 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
1901 }
1902 )
1903
1904 (define_insn "*csinc2<mode>_insn"
1905 [(set (match_operand:GPI 0 "register_operand" "=r")
1906 (plus:GPI (match_operator:GPI 2 "aarch64_comparison_operator"
1907 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1908 (match_operand:GPI 1 "register_operand" "r")))]
1909 ""
1910 "csinc\\t%<w>0, %<w>1, %<w>1, %M2"
1911 [(set_attr "v8type" "csel")
1912 (set_attr "mode" "<MODE>")])
1913
1914 (define_insn "csinc3<mode>_insn"
1915 [(set (match_operand:GPI 0 "register_operand" "=r")
1916 (if_then_else:GPI
1917 (match_operator:GPI 1 "aarch64_comparison_operator"
1918 [(match_operand:CC 2 "cc_register" "") (const_int 0)])
1919 (plus:GPI (match_operand:GPI 3 "register_operand" "r")
1920 (const_int 1))
1921 (match_operand:GPI 4 "aarch64_reg_or_zero" "rZ")))]
1922 ""
1923 "csinc\\t%<w>0, %<w>4, %<w>3, %M1"
1924 [(set_attr "v8type" "csel")
1925 (set_attr "mode" "<MODE>")]
1926 )
1927
1928 (define_insn "*csinv3<mode>_insn"
1929 [(set (match_operand:GPI 0 "register_operand" "=r")
1930 (if_then_else:GPI
1931 (match_operator:GPI 1 "aarch64_comparison_operator"
1932 [(match_operand:CC 2 "cc_register" "") (const_int 0)])
1933 (not:GPI (match_operand:GPI 3 "register_operand" "r"))
1934 (match_operand:GPI 4 "aarch64_reg_or_zero" "rZ")))]
1935 ""
1936 "csinv\\t%<w>0, %<w>4, %<w>3, %M1"
1937 [(set_attr "v8type" "csel")
1938 (set_attr "mode" "<MODE>")])
1939
1940 (define_insn "*csneg3<mode>_insn"
1941 [(set (match_operand:GPI 0 "register_operand" "=r")
1942 (if_then_else:GPI
1943 (match_operator:GPI 1 "aarch64_comparison_operator"
1944 [(match_operand:CC 2 "cc_register" "") (const_int 0)])
1945 (neg:GPI (match_operand:GPI 3 "register_operand" "r"))
1946 (match_operand:GPI 4 "aarch64_reg_or_zero" "rZ")))]
1947 ""
1948 "csneg\\t%<w>0, %<w>4, %<w>3, %M1"
1949 [(set_attr "v8type" "csel")
1950 (set_attr "mode" "<MODE>")])
1951
1952 ;; -------------------------------------------------------------------
1953 ;; Logical operations
1954 ;; -------------------------------------------------------------------
1955
1956 (define_insn "<optab><mode>3"
1957 [(set (match_operand:GPI 0 "register_operand" "=r,rk")
1958 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r")
1959 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>")))]
1960 ""
1961 "<logical>\\t%<w>0, %<w>1, %<w>2"
1962 [(set_attr "v8type" "logic,logic_imm")
1963 (set_attr "mode" "<MODE>")])
1964
1965 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
1966 [(set (match_operand:GPI 0 "register_operand" "=r")
1967 (LOGICAL:GPI (SHIFT:GPI
1968 (match_operand:GPI 1 "register_operand" "r")
1969 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1970 (match_operand:GPI 3 "register_operand" "r")))]
1971 ""
1972 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
1973 [(set_attr "v8type" "logic_shift")
1974 (set_attr "mode" "<MODE>")])
1975
1976 (define_insn "one_cmpl<mode>2"
1977 [(set (match_operand:GPI 0 "register_operand" "=r")
1978 (not:GPI (match_operand:GPI 1 "register_operand" "r")))]
1979 ""
1980 "mvn\\t%<w>0, %<w>1"
1981 [(set_attr "v8type" "logic")
1982 (set_attr "mode" "<MODE>")])
1983
1984 (define_insn "*one_cmpl_<optab><mode>2"
1985 [(set (match_operand:GPI 0 "register_operand" "=r")
1986 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
1987 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
1988 ""
1989 "mvn\\t%<w>0, %<w>1, <shift> %2"
1990 [(set_attr "v8type" "logic_shift")
1991 (set_attr "mode" "<MODE>")])
1992
1993 (define_insn "*<LOGICAL:optab>_one_cmpl<mode>3"
1994 [(set (match_operand:GPI 0 "register_operand" "=r")
1995 (LOGICAL:GPI (not:GPI
1996 (match_operand:GPI 1 "register_operand" "r"))
1997 (match_operand:GPI 2 "register_operand" "r")))]
1998 ""
1999 "<LOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1"
2000 [(set_attr "v8type" "logic")
2001 (set_attr "mode" "<MODE>")])
2002
2003 (define_insn "*<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
2004 [(set (match_operand:GPI 0 "register_operand" "=r")
2005 (LOGICAL:GPI (not:GPI
2006 (SHIFT:GPI
2007 (match_operand:GPI 1 "register_operand" "r")
2008 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2009 (match_operand:GPI 3 "register_operand" "r")))]
2010 ""
2011 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
2012 [(set_attr "v8type" "logic_shift")
2013 (set_attr "mode" "<MODE>")])
2014
2015 (define_insn "clz<mode>2"
2016 [(set (match_operand:GPI 0 "register_operand" "=r")
2017 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
2018 ""
2019 "clz\\t%<w>0, %<w>1"
2020 [(set_attr "v8type" "clz")
2021 (set_attr "mode" "<MODE>")])
2022
2023 (define_expand "ffs<mode>2"
2024 [(match_operand:GPI 0 "register_operand")
2025 (match_operand:GPI 1 "register_operand")]
2026 ""
2027 {
2028 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
2029 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
2030
2031 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
2032 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
2033 emit_insn (gen_csinc3<mode>_insn (operands[0], x, ccreg, operands[0], const0_rtx));
2034 DONE;
2035 }
2036 )
2037
2038 (define_insn "clrsb<mode>2"
2039 [(set (match_operand:GPI 0 "register_operand" "=r")
2040 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_CLS))]
2041 ""
2042 "cls\\t%<w>0, %<w>1"
2043 [(set_attr "v8type" "clz")
2044 (set_attr "mode" "<MODE>")])
2045
2046 (define_insn "rbit<mode>2"
2047 [(set (match_operand:GPI 0 "register_operand" "=r")
2048 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
2049 ""
2050 "rbit\\t%<w>0, %<w>1"
2051 [(set_attr "v8type" "rbit")
2052 (set_attr "mode" "<MODE>")])
2053
2054 (define_expand "ctz<mode>2"
2055 [(match_operand:GPI 0 "register_operand")
2056 (match_operand:GPI 1 "register_operand")]
2057 ""
2058 {
2059 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
2060 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
2061 DONE;
2062 }
2063 )
2064
2065 (define_insn "*and<mode>3nr_compare0"
2066 [(set (reg:CC CC_REGNUM)
2067 (compare:CC
2068 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
2069 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
2070 (const_int 0)))]
2071 ""
2072 "tst\\t%<w>0, %<w>1"
2073 [(set_attr "v8type" "logics")
2074 (set_attr "mode" "<MODE>")])
2075
2076 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
2077 [(set (reg:CC CC_REGNUM)
2078 (compare:CC
2079 (and:GPI (SHIFT:GPI
2080 (match_operand:GPI 0 "register_operand" "r")
2081 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2082 (match_operand:GPI 2 "register_operand" "r"))
2083 (const_int 0)))]
2084 ""
2085 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
2086 [(set_attr "v8type" "logics_shift")
2087 (set_attr "mode" "<MODE>")])
2088
2089 ;; -------------------------------------------------------------------
2090 ;; Shifts
2091 ;; -------------------------------------------------------------------
2092
2093 (define_expand "<optab><mode>3"
2094 [(set (match_operand:GPI 0 "register_operand")
2095 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
2096 (match_operand:QI 2 "nonmemory_operand")))]
2097 ""
2098 {
2099 if (CONST_INT_P (operands[2]))
2100 {
2101 operands[2] = GEN_INT (INTVAL (operands[2])
2102 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2103
2104 if (operands[2] == const0_rtx)
2105 {
2106 emit_insn (gen_mov<mode> (operands[0], operands[1]));
2107 DONE;
2108 }
2109 }
2110 }
2111 )
2112
2113 (define_expand "ashl<mode>3"
2114 [(set (match_operand:SHORT 0 "register_operand")
2115 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
2116 (match_operand:QI 2 "nonmemory_operand")))]
2117 ""
2118 {
2119 if (CONST_INT_P (operands[2]))
2120 {
2121 operands[2] = GEN_INT (INTVAL (operands[2])
2122 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2123
2124 if (operands[2] == const0_rtx)
2125 {
2126 emit_insn (gen_mov<mode> (operands[0], operands[1]));
2127 DONE;
2128 }
2129 }
2130 }
2131 )
2132
2133 (define_expand "rotr<mode>3"
2134 [(set (match_operand:GPI 0 "register_operand")
2135 (rotatert:GPI (match_operand:GPI 1 "register_operand")
2136 (match_operand:QI 2 "nonmemory_operand")))]
2137 ""
2138 {
2139 if (CONST_INT_P (operands[2]))
2140 {
2141 operands[2] = GEN_INT (INTVAL (operands[2])
2142 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2143
2144 if (operands[2] == const0_rtx)
2145 {
2146 emit_insn (gen_mov<mode> (operands[0], operands[1]));
2147 DONE;
2148 }
2149 }
2150 }
2151 )
2152
2153 (define_expand "rotl<mode>3"
2154 [(set (match_operand:GPI 0 "register_operand")
2155 (rotatert:GPI (match_operand:GPI 1 "register_operand")
2156 (match_operand:QI 2 "nonmemory_operand")))]
2157 ""
2158 {
2159 /* (SZ - cnt) % SZ == -cnt % SZ */
2160 if (CONST_INT_P (operands[2]))
2161 {
2162 operands[2] = GEN_INT ((-INTVAL (operands[2]))
2163 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2164 if (operands[2] == const0_rtx)
2165 {
2166 emit_insn (gen_mov<mode> (operands[0], operands[1]));
2167 DONE;
2168 }
2169 }
2170 else
2171 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
2172 NULL_RTX, 1);
2173 }
2174 )
2175
2176 (define_insn "*<optab><mode>3_insn"
2177 [(set (match_operand:GPI 0 "register_operand" "=r")
2178 (SHIFT:GPI
2179 (match_operand:GPI 1 "register_operand" "r")
2180 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "rUs<cmode>")))]
2181 ""
2182 "<shift>\\t%<w>0, %<w>1, %<w>2"
2183 [(set_attr "v8type" "shift")
2184 (set_attr "mode" "<MODE>")]
2185 )
2186
2187 (define_insn "*ashl<mode>3_insn"
2188 [(set (match_operand:SHORT 0 "register_operand" "=r")
2189 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
2190 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "rUss")))]
2191 ""
2192 "lsl\\t%<w>0, %<w>1, %<w>2"
2193 [(set_attr "v8type" "shift")
2194 (set_attr "mode" "<MODE>")]
2195 )
2196
2197 (define_insn "*<optab><mode>3_insn"
2198 [(set (match_operand:SHORT 0 "register_operand" "=r")
2199 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
2200 (match_operand 2 "const_int_operand" "n")))]
2201 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
2202 {
2203 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
2204 return "<bfshift>\t%w0, %w1, %2, %3";
2205 }
2206 [(set_attr "v8type" "bfm")
2207 (set_attr "mode" "<MODE>")]
2208 )
2209
2210 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
2211 [(set (match_operand:GPI 0 "register_operand" "=r")
2212 (ANY_EXTEND:GPI
2213 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
2214 (match_operand 2 "const_int_operand" "n"))))]
2215 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
2216 {
2217 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
2218 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
2219 }
2220 [(set_attr "v8type" "bfm")
2221 (set_attr "mode" "<GPI:MODE>")]
2222 )
2223
2224 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
2225 [(set (match_operand:GPI 0 "register_operand" "=r")
2226 (zero_extend:GPI
2227 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
2228 (match_operand 2 "const_int_operand" "n"))))]
2229 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
2230 {
2231 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
2232 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
2233 }
2234 [(set_attr "v8type" "bfm")
2235 (set_attr "mode" "<GPI:MODE>")]
2236 )
2237
2238 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
2239 [(set (match_operand:GPI 0 "register_operand" "=r")
2240 (sign_extend:GPI
2241 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
2242 (match_operand 2 "const_int_operand" "n"))))]
2243 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
2244 {
2245 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
2246 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
2247 }
2248 [(set_attr "v8type" "bfm")
2249 (set_attr "mode" "<GPI:MODE>")]
2250 )
2251
2252 ;; -------------------------------------------------------------------
2253 ;; Bitfields
2254 ;; -------------------------------------------------------------------
2255
2256 (define_expand "<optab>"
2257 [(set (match_operand:DI 0 "register_operand" "=r")
2258 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand" "r")
2259 (match_operand 2 "const_int_operand" "n")
2260 (match_operand 3 "const_int_operand" "n")))]
2261 ""
2262 ""
2263 )
2264
2265 (define_insn "*<optab><mode>"
2266 [(set (match_operand:GPI 0 "register_operand" "=r")
2267 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
2268 (match_operand 2 "const_int_operand" "n")
2269 (match_operand 3 "const_int_operand" "n")))]
2270 ""
2271 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
2272 [(set_attr "v8type" "bfm")
2273 (set_attr "mode" "<MODE>")]
2274 )
2275
2276 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
2277 [(set (match_operand:GPI 0 "register_operand" "=r")
2278 (ashift:GPI (ANY_EXTEND:GPI
2279 (match_operand:ALLX 1 "register_operand" "r"))
2280 (match_operand 2 "const_int_operand" "n")))]
2281 "UINTVAL (operands[2]) < <GPI:sizen>"
2282 {
2283 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
2284 ? GEN_INT (<ALLX:sizen>)
2285 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
2286 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
2287 }
2288 [(set_attr "v8type" "bfm")
2289 (set_attr "mode" "<GPI:MODE>")]
2290 )
2291
2292 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
2293
2294 (define_insn "*andim_ashift<mode>_bfiz"
2295 [(set (match_operand:GPI 0 "register_operand" "=r")
2296 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2297 (match_operand 2 "const_int_operand" "n"))
2298 (match_operand 3 "const_int_operand" "n")))]
2299 "exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1) >= 0
2300 && (INTVAL (operands[3]) & ((1 << INTVAL (operands[2])) - 1)) == 0"
2301 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
2302 [(set_attr "v8type" "bfm")
2303 (set_attr "mode" "<MODE>")]
2304 )
2305
2306 (define_insn "bswap<mode>2"
2307 [(set (match_operand:GPI 0 "register_operand" "=r")
2308 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
2309 ""
2310 "rev\\t%<w>0, %<w>1"
2311 [(set_attr "v8type" "rev")
2312 (set_attr "mode" "<MODE>")]
2313 )
2314
2315 ;; -------------------------------------------------------------------
2316 ;; Floating-point intrinsics
2317 ;; -------------------------------------------------------------------
2318
2319 ;; trunc - nothrow
2320
2321 (define_insn "btrunc<mode>2"
2322 [(set (match_operand:GPF 0 "register_operand" "=w")
2323 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2324 UNSPEC_FRINTZ))]
2325 "TARGET_FLOAT"
2326 "frintz\\t%<s>0, %<s>1"
2327 [(set_attr "v8type" "frint")
2328 (set_attr "mode" "<MODE>")]
2329 )
2330
2331 (define_insn "*lbtrunc<su_optab><GPF:mode><GPI:mode>2"
2332 [(set (match_operand:GPI 0 "register_operand" "=r")
2333 (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2334 UNSPEC_FRINTZ)))]
2335 "TARGET_FLOAT"
2336 "fcvtz<su>\\t%<GPI:w>0, %<GPF:s>1"
2337 [(set_attr "v8type" "fcvtf2i")
2338 (set_attr "mode" "<GPF:MODE>")
2339 (set_attr "mode2" "<GPI:MODE>")]
2340 )
2341
2342 ;; ceil - nothrow
2343
2344 (define_insn "ceil<mode>2"
2345 [(set (match_operand:GPF 0 "register_operand" "=w")
2346 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2347 UNSPEC_FRINTP))]
2348 "TARGET_FLOAT"
2349 "frintp\\t%<s>0, %<s>1"
2350 [(set_attr "v8type" "frint")
2351 (set_attr "mode" "<MODE>")]
2352 )
2353
2354 (define_insn "lceil<su_optab><GPF:mode><GPI:mode>2"
2355 [(set (match_operand:GPI 0 "register_operand" "=r")
2356 (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2357 UNSPEC_FRINTP)))]
2358 "TARGET_FLOAT"
2359 "fcvtp<su>\\t%<GPI:w>0, %<GPF:s>1"
2360 [(set_attr "v8type" "fcvtf2i")
2361 (set_attr "mode" "<GPF:MODE>")
2362 (set_attr "mode2" "<GPI:MODE>")]
2363 )
2364
2365 ;; floor - nothrow
2366
2367 (define_insn "floor<mode>2"
2368 [(set (match_operand:GPF 0 "register_operand" "=w")
2369 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2370 UNSPEC_FRINTM))]
2371 "TARGET_FLOAT"
2372 "frintm\\t%<s>0, %<s>1"
2373 [(set_attr "v8type" "frint")
2374 (set_attr "mode" "<MODE>")]
2375 )
2376
2377 (define_insn "lfloor<su_optab><GPF:mode><GPI:mode>2"
2378 [(set (match_operand:GPI 0 "register_operand" "=r")
2379 (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2380 UNSPEC_FRINTM)))]
2381 "TARGET_FLOAT"
2382 "fcvtm<su>\\t%<GPI:w>0, %<GPF:s>1"
2383 [(set_attr "v8type" "fcvtf2i")
2384 (set_attr "mode" "<GPF:MODE>")
2385 (set_attr "mode2" "<GPI:MODE>")]
2386 )
2387
2388 ;; nearbyint - nothrow
2389
2390 (define_insn "nearbyint<mode>2"
2391 [(set (match_operand:GPF 0 "register_operand" "=w")
2392 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2393 UNSPEC_FRINTI))]
2394 "TARGET_FLOAT"
2395 "frinti\\t%<s>0, %<s>1"
2396 [(set_attr "v8type" "frint")
2397 (set_attr "mode" "<MODE>")]
2398 )
2399
2400 ;; rint
2401
2402 (define_insn "rint<mode>2"
2403 [(set (match_operand:GPF 0 "register_operand" "=w")
2404 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2405 UNSPEC_FRINTX))]
2406 "TARGET_FLOAT"
2407 "frintx\\t%<s>0, %<s>1"
2408 [(set_attr "v8type" "frint")
2409 (set_attr "mode" "<MODE>")]
2410 )
2411
2412 ;; round - nothrow
2413
2414 (define_insn "round<mode>2"
2415 [(set (match_operand:GPF 0 "register_operand" "=w")
2416 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2417 UNSPEC_FRINTA))]
2418 "TARGET_FLOAT"
2419 "frinta\\t%<s>0, %<s>1"
2420 [(set_attr "v8type" "frint")
2421 (set_attr "mode" "<MODE>")]
2422 )
2423
2424 (define_insn "lround<su_optab><GPF:mode><GPI:mode>2"
2425 [(set (match_operand:GPI 0 "register_operand" "=r")
2426 (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2427 UNSPEC_FRINTA)))]
2428 "TARGET_FLOAT"
2429 "fcvta<su>\\t%<GPI:w>0, %<GPF:s>1"
2430 [(set_attr "v8type" "fcvtf2i")
2431 (set_attr "mode" "<GPF:MODE>")
2432 (set_attr "mode2" "<GPI:MODE>")]
2433 )
2434
2435 ;; fma - no throw
2436
2437 (define_insn "fma<mode>4"
2438 [(set (match_operand:GPF 0 "register_operand" "=w")
2439 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
2440 (match_operand:GPF 2 "register_operand" "w")
2441 (match_operand:GPF 3 "register_operand" "w")))]
2442 "TARGET_FLOAT"
2443 "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
2444 [(set_attr "v8type" "fmadd")
2445 (set_attr "mode" "<MODE>")]
2446 )
2447
2448 (define_insn "fnma<mode>4"
2449 [(set (match_operand:GPF 0 "register_operand" "=w")
2450 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
2451 (match_operand:GPF 2 "register_operand" "w")
2452 (match_operand:GPF 3 "register_operand" "w")))]
2453 "TARGET_FLOAT"
2454 "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
2455 [(set_attr "v8type" "fmadd")
2456 (set_attr "mode" "<MODE>")]
2457 )
2458
2459 (define_insn "fms<mode>4"
2460 [(set (match_operand:GPF 0 "register_operand" "=w")
2461 (fma:GPF (match_operand:GPF 1 "register_operand" "w")
2462 (match_operand:GPF 2 "register_operand" "w")
2463 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
2464 "TARGET_FLOAT"
2465 "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
2466 [(set_attr "v8type" "fmadd")
2467 (set_attr "mode" "<MODE>")]
2468 )
2469
2470 (define_insn "fnms<mode>4"
2471 [(set (match_operand:GPF 0 "register_operand" "=w")
2472 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
2473 (match_operand:GPF 2 "register_operand" "w")
2474 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
2475 "TARGET_FLOAT"
2476 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
2477 [(set_attr "v8type" "fmadd")
2478 (set_attr "mode" "<MODE>")]
2479 )
2480
2481 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
2482 (define_insn "*fnmadd<mode>4"
2483 [(set (match_operand:GPF 0 "register_operand" "=w")
2484 (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
2485 (match_operand:GPF 2 "register_operand" "w")
2486 (match_operand:GPF 3 "register_operand" "w"))))]
2487 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
2488 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
2489 [(set_attr "v8type" "fmadd")
2490 (set_attr "mode" "<MODE>")]
2491 )
2492
2493 ;; -------------------------------------------------------------------
2494 ;; Floating-point conversions
2495 ;; -------------------------------------------------------------------
2496
2497 (define_insn "extendsfdf2"
2498 [(set (match_operand:DF 0 "register_operand" "=w")
2499 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
2500 "TARGET_FLOAT"
2501 "fcvt\\t%d0, %s1"
2502 [(set_attr "v8type" "fcvt")
2503 (set_attr "mode" "DF")
2504 (set_attr "mode2" "SF")]
2505 )
2506
2507 (define_insn "truncdfsf2"
2508 [(set (match_operand:SF 0 "register_operand" "=w")
2509 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
2510 "TARGET_FLOAT"
2511 "fcvt\\t%s0, %d1"
2512 [(set_attr "v8type" "fcvt")
2513 (set_attr "mode" "SF")
2514 (set_attr "mode2" "DF")]
2515 )
2516
2517 (define_insn "fix_trunc<GPF:mode><GPI:mode>2"
2518 [(set (match_operand:GPI 0 "register_operand" "=r")
2519 (fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
2520 "TARGET_FLOAT"
2521 "fcvtzs\\t%<GPI:w>0, %<GPF:s>1"
2522 [(set_attr "v8type" "fcvtf2i")
2523 (set_attr "mode" "<GPF:MODE>")
2524 (set_attr "mode2" "<GPI:MODE>")]
2525 )
2526
2527 (define_insn "fixuns_trunc<GPF:mode><GPI:mode>2"
2528 [(set (match_operand:GPI 0 "register_operand" "=r")
2529 (unsigned_fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
2530 "TARGET_FLOAT"
2531 "fcvtzu\\t%<GPI:w>0, %<GPF:s>1"
2532 [(set_attr "v8type" "fcvtf2i")
2533 (set_attr "mode" "<GPF:MODE>")
2534 (set_attr "mode2" "<GPI:MODE>")]
2535 )
2536
2537 (define_insn "float<GPI:mode><GPF:mode>2"
2538 [(set (match_operand:GPF 0 "register_operand" "=w")
2539 (float:GPF (match_operand:GPI 1 "register_operand" "r")))]
2540 "TARGET_FLOAT"
2541 "scvtf\\t%<GPF:s>0, %<GPI:w>1"
2542 [(set_attr "v8type" "fcvti2f")
2543 (set_attr "mode" "<GPF:MODE>")
2544 (set_attr "mode2" "<GPI:MODE>")]
2545 )
2546
2547 (define_insn "floatuns<GPI:mode><GPF:mode>2"
2548 [(set (match_operand:GPF 0 "register_operand" "=w")
2549 (unsigned_float:GPF (match_operand:GPI 1 "register_operand" "r")))]
2550 "TARGET_FLOAT"
2551 "ucvtf\\t%<GPF:s>0, %<GPI:w>1"
2552 [(set_attr "v8type" "fcvt")
2553 (set_attr "mode" "<GPF:MODE>")
2554 (set_attr "mode2" "<GPI:MODE>")]
2555 )
2556
2557 ;; -------------------------------------------------------------------
2558 ;; Floating-point arithmetic
2559 ;; -------------------------------------------------------------------
2560
2561 (define_insn "add<mode>3"
2562 [(set (match_operand:GPF 0 "register_operand" "=w")
2563 (plus:GPF
2564 (match_operand:GPF 1 "register_operand" "w")
2565 (match_operand:GPF 2 "register_operand" "w")))]
2566 "TARGET_FLOAT"
2567 "fadd\\t%<s>0, %<s>1, %<s>2"
2568 [(set_attr "v8type" "fadd")
2569 (set_attr "mode" "<MODE>")]
2570 )
2571
2572 (define_insn "sub<mode>3"
2573 [(set (match_operand:GPF 0 "register_operand" "=w")
2574 (minus:GPF
2575 (match_operand:GPF 1 "register_operand" "w")
2576 (match_operand:GPF 2 "register_operand" "w")))]
2577 "TARGET_FLOAT"
2578 "fsub\\t%<s>0, %<s>1, %<s>2"
2579 [(set_attr "v8type" "fadd")
2580 (set_attr "mode" "<MODE>")]
2581 )
2582
2583 (define_insn "mul<mode>3"
2584 [(set (match_operand:GPF 0 "register_operand" "=w")
2585 (mult:GPF
2586 (match_operand:GPF 1 "register_operand" "w")
2587 (match_operand:GPF 2 "register_operand" "w")))]
2588 "TARGET_FLOAT"
2589 "fmul\\t%<s>0, %<s>1, %<s>2"
2590 [(set_attr "v8type" "fmul")
2591 (set_attr "mode" "<MODE>")]
2592 )
2593
2594 (define_insn "*fnmul<mode>3"
2595 [(set (match_operand:GPF 0 "register_operand" "=w")
2596 (mult:GPF
2597 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
2598 (match_operand:GPF 2 "register_operand" "w")))]
2599 "TARGET_FLOAT"
2600 "fnmul\\t%<s>0, %<s>1, %<s>2"
2601 [(set_attr "v8type" "fmul")
2602 (set_attr "mode" "<MODE>")]
2603 )
2604
2605 (define_insn "div<mode>3"
2606 [(set (match_operand:GPF 0 "register_operand" "=w")
2607 (div:GPF
2608 (match_operand:GPF 1 "register_operand" "w")
2609 (match_operand:GPF 2 "register_operand" "w")))]
2610 "TARGET_FLOAT"
2611 "fdiv\\t%<s>0, %<s>1, %<s>2"
2612 [(set_attr "v8type" "fdiv")
2613 (set_attr "mode" "<MODE>")]
2614 )
2615
2616 (define_insn "neg<mode>2"
2617 [(set (match_operand:GPF 0 "register_operand" "=w")
2618 (neg:GPF (match_operand:GPF 1 "register_operand" "w")))]
2619 "TARGET_FLOAT"
2620 "fneg\\t%<s>0, %<s>1"
2621 [(set_attr "v8type" "ffarith")
2622 (set_attr "mode" "<MODE>")]
2623 )
2624
2625 (define_insn "sqrt<mode>2"
2626 [(set (match_operand:GPF 0 "register_operand" "=w")
2627 (sqrt:GPF (match_operand:GPF 1 "register_operand" "w")))]
2628 "TARGET_FLOAT"
2629 "fsqrt\\t%<s>0, %<s>1"
2630 [(set_attr "v8type" "fsqrt")
2631 (set_attr "mode" "<MODE>")]
2632 )
2633
2634 (define_insn "abs<mode>2"
2635 [(set (match_operand:GPF 0 "register_operand" "=w")
2636 (abs:GPF (match_operand:GPF 1 "register_operand" "w")))]
2637 "TARGET_FLOAT"
2638 "fabs\\t%<s>0, %<s>1"
2639 [(set_attr "v8type" "ffarith")
2640 (set_attr "mode" "<MODE>")]
2641 )
2642
2643 ;; Given that smax/smin do not specify the result when either input is NaN,
2644 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
2645 ;; for smin.
2646
2647 (define_insn "smax<mode>3"
2648 [(set (match_operand:GPF 0 "register_operand" "=w")
2649 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
2650 (match_operand:GPF 2 "register_operand" "w")))]
2651 "TARGET_FLOAT"
2652 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
2653 [(set_attr "v8type" "fminmax")
2654 (set_attr "mode" "<MODE>")]
2655 )
2656
2657 (define_insn "smin<mode>3"
2658 [(set (match_operand:GPF 0 "register_operand" "=w")
2659 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
2660 (match_operand:GPF 2 "register_operand" "w")))]
2661 "TARGET_FLOAT"
2662 "fminnm\\t%<s>0, %<s>1, %<s>2"
2663 [(set_attr "v8type" "fminmax")
2664 (set_attr "mode" "<MODE>")]
2665 )
2666
2667 ;; -------------------------------------------------------------------
2668 ;; Reload support
2669 ;; -------------------------------------------------------------------
2670
2671 ;; Reload SP+imm where imm cannot be handled by a single ADD instruction.
2672 ;; Must load imm into a scratch register and copy SP to the dest reg before
2673 ;; adding, since SP cannot be used as a source register in an ADD
2674 ;; instruction.
2675 (define_expand "reload_sp_immediate"
2676 [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
2677 (match_operand:DI 1 "" ""))
2678 (clobber (match_operand:TI 2 "register_operand" "=&r"))])]
2679 ""
2680 {
2681 rtx sp = XEXP (operands[1], 0);
2682 rtx val = XEXP (operands[1], 1);
2683 unsigned regno = REGNO (operands[2]);
2684 rtx scratch = operands[1];
2685 gcc_assert (GET_CODE (operands[1]) == PLUS);
2686 gcc_assert (sp == stack_pointer_rtx);
2687 gcc_assert (CONST_INT_P (val));
2688
2689 /* It is possible that one of the registers we got for operands[2]
2690 might coincide with that of operands[0] (which is why we made
2691 it TImode). Pick the other one to use as our scratch. */
2692 if (regno == REGNO (operands[0]))
2693 regno++;
2694 scratch = gen_rtx_REG (DImode, regno);
2695
2696 emit_move_insn (scratch, val);
2697 emit_move_insn (operands[0], sp);
2698 emit_insn (gen_adddi3 (operands[0], operands[0], scratch));
2699 DONE;
2700 }
2701 )
2702
2703 (define_expand "aarch64_reload_mov<mode>"
2704 [(set (match_operand:TX 0 "register_operand" "=w")
2705 (match_operand:TX 1 "register_operand" "w"))
2706 (clobber (match_operand:DI 2 "register_operand" "=&r"))
2707 ]
2708 ""
2709 {
2710 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
2711 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
2712 gen_aarch64_movtilow_tilow (op0, op1);
2713 gen_aarch64_movdi_tihigh (operands[2], op1);
2714 gen_aarch64_movtihigh_di (op0, operands[2]);
2715 DONE;
2716 }
2717 )
2718
2719 ;; The following secondary reload helpers patterns are invoked
2720 ;; after or during reload as we don't want these patterns to start
2721 ;; kicking in during the combiner.
2722
2723 (define_insn "aarch64_movdi_tilow"
2724 [(set (match_operand:DI 0 "register_operand" "=r")
2725 (truncate:DI (match_operand:TI 1 "register_operand" "w")))]
2726 "reload_completed || reload_in_progress"
2727 "fmov\\t%x0, %d1"
2728 [(set_attr "v8type" "fmovf2i")
2729 (set_attr "mode" "DI")
2730 (set_attr "length" "4")
2731 ])
2732
2733 (define_insn "aarch64_movdi_tihigh"
2734 [(set (match_operand:DI 0 "register_operand" "=r")
2735 (truncate:DI
2736 (lshiftrt:TI (match_operand:TI 1 "register_operand" "w")
2737 (const_int 64))))]
2738 "reload_completed || reload_in_progress"
2739 "fmov\\t%x0, %1.d[1]"
2740 [(set_attr "v8type" "fmovf2i")
2741 (set_attr "mode" "DI")
2742 (set_attr "length" "4")
2743 ])
2744
2745 (define_insn "aarch64_movtihigh_di"
2746 [(set (zero_extract:TI (match_operand:TI 0 "register_operand" "+w")
2747 (const_int 64) (const_int 64))
2748 (zero_extend:TI (match_operand:DI 1 "register_operand" "r")))]
2749 "reload_completed || reload_in_progress"
2750 "fmov\\t%0.d[1], %x1"
2751
2752 [(set_attr "v8type" "fmovi2f")
2753 (set_attr "mode" "DI")
2754 (set_attr "length" "4")
2755 ])
2756
2757 (define_insn "aarch64_movtilow_di"
2758 [(set (match_operand:TI 0 "register_operand" "=w")
2759 (zero_extend:TI (match_operand:DI 1 "register_operand" "r")))]
2760 "reload_completed || reload_in_progress"
2761 "fmov\\t%d0, %x1"
2762
2763 [(set_attr "v8type" "fmovi2f")
2764 (set_attr "mode" "DI")
2765 (set_attr "length" "4")
2766 ])
2767
2768 (define_insn "aarch64_movtilow_tilow"
2769 [(set (match_operand:TI 0 "register_operand" "=w")
2770 (zero_extend:TI
2771 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
2772 "reload_completed || reload_in_progress"
2773 "fmov\\t%d0, %d1"
2774
2775 [(set_attr "v8type" "fmovi2f")
2776 (set_attr "mode" "DI")
2777 (set_attr "length" "4")
2778 ])
2779
2780 ;; There is a deliberate reason why the parameters of high and lo_sum's
2781 ;; don't have modes for ADRP and ADD instructions. This is to allow high
2782 ;; and lo_sum's to be used with the labels defining the jump tables in
2783 ;; rodata section.
2784
2785 (define_insn "add_losym"
2786 [(set (match_operand:DI 0 "register_operand" "=r")
2787 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2788 (match_operand 2 "aarch64_valid_symref" "S")))]
2789 ""
2790 "add\\t%0, %1, :lo12:%a2"
2791 [(set_attr "v8type" "alu")
2792 (set_attr "mode" "DI")]
2793
2794 )
2795
2796 (define_insn "ldr_got_small"
2797 [(set (match_operand:DI 0 "register_operand" "=r")
2798 (unspec:DI [(mem:DI (lo_sum:DI
2799 (match_operand:DI 1 "register_operand" "r")
2800 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
2801 UNSPEC_GOTSMALLPIC))]
2802 ""
2803 "ldr\\t%0, [%1, #:got_lo12:%a2]"
2804 [(set_attr "v8type" "load1")
2805 (set_attr "mode" "DI")]
2806 )
2807
2808 (define_insn "aarch64_load_tp_hard"
2809 [(set (match_operand:DI 0 "register_operand" "=r")
2810 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
2811 ""
2812 "mrs\\t%0, tpidr_el0"
2813 [(set_attr "v8type" "mrs")
2814 (set_attr "mode" "DI")]
2815 )
2816
2817 ;; The TLS ABI specifically requires that the compiler does not schedule
2818 ;; instructions in the TLS stubs, in order to enable linker relaxation.
2819 ;; Therefore we treat the stubs as an atomic sequence.
2820 (define_expand "tlsgd_small"
2821 [(parallel [(set (match_operand 0 "register_operand" "")
2822 (call (mem:DI (match_dup 2)) (const_int 1)))
2823 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
2824 (clobber (reg:DI LR_REGNUM))])]
2825 ""
2826 {
2827 operands[2] = aarch64_tls_get_addr ();
2828 })
2829
2830 (define_insn "*tlsgd_small"
2831 [(set (match_operand 0 "register_operand" "")
2832 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
2833 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
2834 (clobber (reg:DI LR_REGNUM))
2835 ]
2836 ""
2837 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
2838 [(set_attr "v8type" "call")
2839 (set_attr "length" "16")])
2840
2841 (define_insn "tlsie_small"
2842 [(set (match_operand:DI 0 "register_operand" "=r")
2843 (unspec:DI [(match_operand:DI 1 "aarch64_tls_ie_symref" "S")]
2844 UNSPEC_GOTSMALLTLS))]
2845 ""
2846 "adrp\\t%0, %A1\;ldr\\t%0, [%0, #%L1]"
2847 [(set_attr "v8type" "load1")
2848 (set_attr "mode" "DI")
2849 (set_attr "length" "8")]
2850 )
2851
2852 (define_insn "tlsle_small"
2853 [(set (match_operand:DI 0 "register_operand" "=r")
2854 (unspec:DI [(match_operand:DI 1 "register_operand" "r")
2855 (match_operand:DI 2 "aarch64_tls_le_symref" "S")]
2856 UNSPEC_GOTSMALLTLS))]
2857 ""
2858 "add\\t%0, %1, #%G2\;add\\t%0, %0, #%L2"
2859 [(set_attr "v8type" "alu")
2860 (set_attr "mode" "DI")
2861 (set_attr "length" "8")]
2862 )
2863
2864 (define_insn "tlsdesc_small"
2865 [(set (reg:DI R0_REGNUM)
2866 (unspec:DI [(match_operand:DI 0 "aarch64_valid_symref" "S")]
2867 UNSPEC_TLSDESC))
2868 (clobber (reg:DI LR_REGNUM))
2869 (clobber (match_scratch:DI 1 "=r"))]
2870 "TARGET_TLS_DESC"
2871 "adrp\\tx0, %A0\;ldr\\t%1, [x0, #%L0]\;add\\tx0, x0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
2872 [(set_attr "v8type" "call")
2873 (set_attr "length" "16")])
2874
2875 (define_insn "stack_tie"
2876 [(set (mem:BLK (scratch))
2877 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
2878 (match_operand:DI 1 "register_operand" "rk")]
2879 UNSPEC_PRLG_STK))]
2880 ""
2881 ""
2882 [(set_attr "length" "0")]
2883 )
2884
2885 ;; Named pattern for expanding thread pointer reference.
2886 (define_expand "get_thread_pointerdi"
2887 [(match_operand:DI 0 "register_operand" "=r")]
2888 ""
2889 {
2890 rtx tmp = aarch64_load_tp (operands[0]);
2891 if (tmp != operands[0])
2892 emit_move_insn (operands[0], tmp);
2893 DONE;
2894 })
2895
2896 ;; AdvSIMD Stuff
2897 (include "aarch64-simd.md")
2898
2899 ;; Atomic Operations
2900 (include "atomics.md")