Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / gcc / config / aarch64 / aarch64.md
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2013 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:GPI 1 "const_int_operand" "n"))
844         (match_operand:GPI 2 "const_int_operand" "n"))]
845   "INTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
846    && INTVAL (operands[1]) % 16 == 0
847    && UINTVAL (operands[2]) <= 0xffff"
848   "movk\\t%<w>0, %X2, 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  ,w,m,r,m ,r")
919         (match_operand:SF 1 "general_operand"      "?rY, w,w,Ufc,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    fmov\\t%s0, %1
927    ldr\\t%s0, %1
928    str\\t%s1, %0
929    ldr\\t%w0, %1
930    str\\t%w1, %0
931    mov\\t%w0, %w1"
932   [(set_attr "v8type" "fmovi2f,fmovf2i,\
933                        fmov,fconst,fpsimd_load,\
934                        fpsimd_store,fpsimd_load,fpsimd_store,fmov")
935    (set_attr "mode" "SF")]
936 )
937
938 (define_insn "*movdf_aarch64"
939   [(set (match_operand:DF 0 "nonimmediate_operand" "=w, ?r,w,w  ,w,m,r,m ,r")
940         (match_operand:DF 1 "general_operand"      "?rY, w,w,Ufc,m,w,m,rY,r"))]
941   "TARGET_FLOAT && (register_operand (operands[0], DFmode)
942     || register_operand (operands[1], DFmode))"
943   "@
944    fmov\\t%d0, %x1
945    fmov\\t%x0, %d1
946    fmov\\t%d0, %d1
947    fmov\\t%d0, %1
948    ldr\\t%d0, %1
949    str\\t%d1, %0
950    ldr\\t%x0, %1
951    str\\t%x1, %0
952    mov\\t%x0, %x1"
953   [(set_attr "v8type" "fmovi2f,fmovf2i,\
954                        fmov,fconst,fpsimd_load,\
955                        fpsimd_store,fpsimd_load,fpsimd_store,move")
956    (set_attr "mode" "DF")]
957 )
958
959 (define_expand "movtf"
960   [(set (match_operand:TF 0 "nonimmediate_operand" "")
961         (match_operand:TF 1 "general_operand" ""))]
962   ""
963   "
964     if (!TARGET_FLOAT)
965      {
966         sorry (\"%qs and floating point code\", \"-mgeneral-regs-only\");
967         FAIL;
968      }
969
970     if (GET_CODE (operands[0]) == MEM)
971       operands[1] = force_reg (TFmode, operands[1]);
972   "
973 )
974
975 (define_insn "*movtf_aarch64"
976   [(set (match_operand:TF 0
977          "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump")
978         (match_operand:TF 1
979          "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,Ump,?rY"))]
980   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
981     || register_operand (operands[1], TFmode))"
982   "@
983    orr\\t%0.16b, %1.16b, %1.16b
984    mov\\t%0, %1\;mov\\t%H0, %H1
985    fmov\\t%d0, %Q1\;fmov\\t%0.d[1], %R1
986    fmov\\t%Q0, %d1\;fmov\\t%R0, %1.d[1]
987    movi\\t%0.2d, #0
988    fmov\\t%s0, wzr
989    ldr\\t%q0, %1
990    str\\t%q1, %0
991    ldp\\t%0, %H0, %1
992    stp\\t%1, %H1, %0"
993   [(set_attr "v8type" "logic,move2,fmovi2f,fmovf2i,fconst,fconst,fpsimd_load,fpsimd_store,fpsimd_load2,fpsimd_store2")
994    (set_attr "mode" "DF,DF,DF,DF,DF,DF,TF,TF,DF,DF")
995    (set_attr "length" "4,8,8,8,4,4,4,4,4,4")
996    (set_attr "fp" "*,*,yes,yes,*,yes,yes,yes,*,*")
997    (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*")]
998 )
999
1000 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1001 ;; fairly lax checking on the second memory operation.
1002 (define_insn "load_pair<mode>"
1003   [(set (match_operand:GPI 0 "register_operand" "=r")
1004         (match_operand:GPI 1 "aarch64_mem_pair_operand" "Ump"))
1005    (set (match_operand:GPI 2 "register_operand" "=r")
1006         (match_operand:GPI 3 "memory_operand" "m"))]
1007   "rtx_equal_p (XEXP (operands[3], 0),
1008                 plus_constant (Pmode,
1009                                XEXP (operands[1], 0),
1010                                GET_MODE_SIZE (<MODE>mode)))"
1011   "ldp\\t%<w>0, %<w>2, %1"
1012   [(set_attr "v8type" "load2")
1013    (set_attr "mode" "<MODE>")]
1014 )
1015
1016 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1017 ;; fairly lax checking on the second memory operation.
1018 (define_insn "store_pair<mode>"
1019   [(set (match_operand:GPI 0 "aarch64_mem_pair_operand" "=Ump")
1020         (match_operand:GPI 1 "register_operand" "r"))
1021    (set (match_operand:GPI 2 "memory_operand" "=m")
1022         (match_operand:GPI 3 "register_operand" "r"))]
1023   "rtx_equal_p (XEXP (operands[2], 0),
1024                 plus_constant (Pmode,
1025                                XEXP (operands[0], 0),
1026                                GET_MODE_SIZE (<MODE>mode)))"
1027   "stp\\t%<w>1, %<w>3, %0"
1028   [(set_attr "v8type" "store2")
1029    (set_attr "mode" "<MODE>")]
1030 )
1031
1032 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1033 ;; fairly lax checking on the second memory operation.
1034 (define_insn "load_pair<mode>"
1035   [(set (match_operand:GPF 0 "register_operand" "=w")
1036         (match_operand:GPF 1 "aarch64_mem_pair_operand" "Ump"))
1037    (set (match_operand:GPF 2 "register_operand" "=w")
1038         (match_operand:GPF 3 "memory_operand" "m"))]
1039   "rtx_equal_p (XEXP (operands[3], 0),
1040                 plus_constant (Pmode,
1041                                XEXP (operands[1], 0),
1042                                GET_MODE_SIZE (<MODE>mode)))"
1043   "ldp\\t%<w>0, %<w>2, %1"
1044   [(set_attr "v8type" "fpsimd_load2")
1045    (set_attr "mode" "<MODE>")]
1046 )
1047
1048 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1049 ;; fairly lax checking on the second memory operation.
1050 (define_insn "store_pair<mode>"
1051   [(set (match_operand:GPF 0 "aarch64_mem_pair_operand" "=Ump")
1052         (match_operand:GPF 1 "register_operand" "w"))
1053    (set (match_operand:GPF 2 "memory_operand" "=m")
1054         (match_operand:GPF 3 "register_operand" "w"))]
1055   "rtx_equal_p (XEXP (operands[2], 0),
1056                 plus_constant (Pmode,
1057                                XEXP (operands[0], 0),
1058                                GET_MODE_SIZE (<MODE>mode)))"
1059   "stp\\t%<w>1, %<w>3, %0"
1060   [(set_attr "v8type" "fpsimd_load2")
1061    (set_attr "mode" "<MODE>")]
1062 )
1063
1064 ;; Load pair with writeback.  This is primarily used in function epilogues
1065 ;; when restoring [fp,lr]
1066 (define_insn "loadwb_pair<GPI:mode>_<PTR:mode>"
1067   [(parallel
1068     [(set (match_operand:PTR 0 "register_operand" "=k")
1069           (plus:PTR (match_operand:PTR 1 "register_operand" "0")
1070                   (match_operand:PTR 4 "const_int_operand" "n")))
1071      (set (match_operand:GPI 2 "register_operand" "=r")
1072           (mem:GPI (plus:PTR (match_dup 1)
1073                    (match_dup 4))))
1074      (set (match_operand:GPI 3 "register_operand" "=r")
1075           (mem:GPI (plus:PTR (match_dup 1)
1076                    (match_operand:PTR 5 "const_int_operand" "n"))))])]
1077   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1078   "ldp\\t%<w>2, %<w>3, [%1], %4"
1079   [(set_attr "v8type" "load2")
1080    (set_attr "mode" "<GPI:MODE>")]
1081 )
1082
1083 ;; Store pair with writeback.  This is primarily used in function prologues
1084 ;; when saving [fp,lr]
1085 (define_insn "storewb_pair<GPI:mode>_<PTR:mode>"
1086   [(parallel
1087     [(set (match_operand:PTR 0 "register_operand" "=&k")
1088           (plus:PTR (match_operand:PTR 1 "register_operand" "0")
1089                   (match_operand:PTR 4 "const_int_operand" "n")))
1090      (set (mem:GPI (plus:PTR (match_dup 0)
1091                    (match_dup 4)))
1092           (match_operand:GPI 2 "register_operand" "r"))
1093      (set (mem:GPI (plus:PTR (match_dup 0)
1094                    (match_operand:PTR 5 "const_int_operand" "n")))
1095           (match_operand:GPI 3 "register_operand" "r"))])]
1096   "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1097   "stp\\t%<w>2, %<w>3, [%0, %4]!"
1098   [(set_attr "v8type" "store2")
1099    (set_attr "mode" "<GPI:MODE>")]
1100 )
1101
1102 ;; -------------------------------------------------------------------
1103 ;; Sign/Zero extension
1104 ;; -------------------------------------------------------------------
1105
1106 (define_expand "<optab>sidi2"
1107   [(set (match_operand:DI 0 "register_operand")
1108         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1109   ""
1110 )
1111
1112 (define_insn "*extendsidi2_aarch64"
1113   [(set (match_operand:DI 0 "register_operand" "=r,r")
1114         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1115   ""
1116   "@
1117    sxtw\t%0, %w1
1118    ldrsw\t%0, %1"
1119   [(set_attr "v8type" "extend,load1")
1120    (set_attr "mode" "DI")]
1121 )
1122
1123 (define_insn "*zero_extendsidi2_aarch64"
1124   [(set (match_operand:DI 0 "register_operand" "=r,r")
1125         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1126   ""
1127   "@
1128    uxtw\t%0, %w1
1129    ldr\t%w0, %1"
1130   [(set_attr "v8type" "extend,load1")
1131    (set_attr "mode" "DI")]
1132 )
1133
1134 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1135   [(set (match_operand:GPI 0 "register_operand")
1136         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1137   ""
1138 )
1139
1140 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1141   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1142         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1143   ""
1144   "@
1145    sxt<SHORT:size>\t%<GPI:w>0, %w1
1146    ldrs<SHORT:size>\t%<GPI:w>0, %1"
1147   [(set_attr "v8type" "extend,load1")
1148    (set_attr "mode" "<GPI:MODE>")]
1149 )
1150
1151 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1152   [(set (match_operand:GPI 0 "register_operand" "=r,r")
1153         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1154   ""
1155   "@
1156    uxt<SHORT:size>\t%<GPI:w>0, %w1
1157    ldr<SHORT:size>\t%w0, %1"
1158   [(set_attr "v8type" "extend,load1")
1159    (set_attr "mode" "<GPI:MODE>")]
1160 )
1161
1162 (define_expand "<optab>qihi2"
1163   [(set (match_operand:HI 0 "register_operand")
1164         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1165   ""
1166 )
1167
1168 (define_insn "*<optab>qihi2_aarch64"
1169   [(set (match_operand:HI 0 "register_operand" "=r,r")
1170         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1171   ""
1172   "@
1173    <su>xtb\t%w0, %w1
1174    <ldrxt>b\t%w0, %1"
1175   [(set_attr "v8type" "extend,load1")
1176    (set_attr "mode" "HI")]
1177 )
1178
1179 ;; -------------------------------------------------------------------
1180 ;; Simple arithmetic
1181 ;; -------------------------------------------------------------------
1182
1183 (define_expand "add<mode>3"
1184   [(set
1185     (match_operand:GPI 0 "register_operand" "")
1186     (plus:GPI (match_operand:GPI 1 "register_operand" "")
1187               (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
1188   ""
1189   "
1190   if (! aarch64_plus_operand (operands[2], VOIDmode))
1191     {
1192       rtx subtarget = ((optimize && can_create_pseudo_p ())
1193                        ? gen_reg_rtx (<MODE>mode) : operands[0]);
1194       HOST_WIDE_INT imm = INTVAL (operands[2]);
1195
1196       if (imm < 0)
1197         imm = -(-imm & ~0xfff);
1198       else
1199         imm &= ~0xfff;
1200
1201       emit_insn (gen_add<mode>3 (subtarget, operands[1], GEN_INT (imm)));
1202       operands[1] = subtarget;
1203       operands[2] = GEN_INT (INTVAL (operands[2]) - imm);
1204     }
1205   "
1206 )
1207
1208 (define_insn "*addsi3_aarch64"
1209   [(set
1210     (match_operand:SI 0 "register_operand" "=rk,rk,rk")
1211     (plus:SI
1212      (match_operand:SI 1 "register_operand" "%rk,rk,rk")
1213      (match_operand:SI 2 "aarch64_plus_operand" "I,r,J")))]
1214   ""
1215   "@
1216   add\\t%w0, %w1, %2
1217   add\\t%w0, %w1, %w2
1218   sub\\t%w0, %w1, #%n2"
1219   [(set_attr "v8type" "alu")
1220    (set_attr "mode" "SI")]
1221 )
1222
1223 ;; zero_extend version of above
1224 (define_insn "*addsi3_aarch64_uxtw"
1225   [(set
1226     (match_operand:DI 0 "register_operand" "=rk,rk,rk")
1227     (zero_extend:DI
1228      (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk")
1229               (match_operand:SI 2 "aarch64_plus_operand" "I,r,J"))))]
1230   ""
1231   "@
1232   add\\t%w0, %w1, %2
1233   add\\t%w0, %w1, %w2
1234   sub\\t%w0, %w1, #%n2"
1235   [(set_attr "v8type" "alu")
1236    (set_attr "mode" "SI")]
1237 )
1238
1239 (define_insn "*adddi3_aarch64"
1240   [(set
1241     (match_operand:DI 0 "register_operand" "=rk,rk,rk,!w")
1242     (plus:DI
1243      (match_operand:DI 1 "register_operand" "%rk,rk,rk,!w")
1244      (match_operand:DI 2 "aarch64_plus_operand" "I,r,J,!w")))]
1245   ""
1246   "@
1247   add\\t%x0, %x1, %2
1248   add\\t%x0, %x1, %x2
1249   sub\\t%x0, %x1, #%n2
1250   add\\t%d0, %d1, %d2"
1251   [(set_attr "v8type" "alu")
1252    (set_attr "mode" "DI")
1253    (set_attr "simd" "*,*,*,yes")]
1254 )
1255
1256 (define_insn "*add<mode>3_compare0"
1257   [(set (reg:CC_NZ CC_REGNUM)
1258         (compare:CC_NZ
1259          (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r")
1260                    (match_operand:GPI 2 "aarch64_plus_operand" "rI,J"))
1261          (const_int 0)))
1262    (set (match_operand:GPI 0 "register_operand" "=r,r")
1263         (plus:GPI (match_dup 1) (match_dup 2)))]
1264   ""
1265   "@
1266   adds\\t%<w>0, %<w>1, %<w>2
1267   subs\\t%<w>0, %<w>1, #%n2"
1268   [(set_attr "v8type" "alus")
1269    (set_attr "mode" "<MODE>")]
1270 )
1271
1272 ;; zero_extend version of above
1273 (define_insn "*addsi3_compare0_uxtw"
1274   [(set (reg:CC_NZ CC_REGNUM)
1275         (compare:CC_NZ
1276          (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
1277                   (match_operand:SI 2 "aarch64_plus_operand" "rI,J"))
1278          (const_int 0)))
1279    (set (match_operand:DI 0 "register_operand" "=r,r")
1280         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1281   ""
1282   "@
1283   adds\\t%w0, %w1, %w2
1284   subs\\t%w0, %w1, #%n2"
1285   [(set_attr "v8type" "alus")
1286    (set_attr "mode" "SI")]
1287 )
1288
1289 (define_insn "*add<mode>3nr_compare0"
1290   [(set (reg:CC_NZ CC_REGNUM)
1291         (compare:CC_NZ
1292          (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r")
1293                    (match_operand:GPI 1 "aarch64_plus_operand" "rI,J"))
1294          (const_int 0)))]
1295   ""
1296   "@
1297   cmn\\t%<w>0, %<w>1
1298   cmp\\t%<w>0, #%n1"
1299   [(set_attr "v8type" "alus")
1300    (set_attr "mode" "<MODE>")]
1301 )
1302
1303 (define_insn "*compare_neg<mode>"
1304   [(set (reg:CC CC_REGNUM)
1305         (compare:CC
1306          (match_operand:GPI 0 "register_operand" "r")
1307          (neg:GPI (match_operand:GPI 1 "register_operand" "r"))))]
1308   ""
1309   "cmn\\t%<w>0, %<w>1"
1310   [(set_attr "v8type" "alus")
1311    (set_attr "mode" "<MODE>")]
1312 )
1313
1314 (define_insn "*add_<shift>_<mode>"
1315   [(set (match_operand:GPI 0 "register_operand" "=rk")
1316         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
1317                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1318                   (match_operand:GPI 3 "register_operand" "r")))]
1319   ""
1320   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1321   [(set_attr "v8type" "alu_shift")
1322    (set_attr "mode" "<MODE>")]
1323 )
1324
1325 ;; zero_extend version of above
1326 (define_insn "*add_<shift>_si_uxtw"
1327   [(set (match_operand:DI 0 "register_operand" "=rk")
1328         (zero_extend:DI
1329          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
1330                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
1331                   (match_operand:SI 3 "register_operand" "r"))))]
1332   ""
1333   "add\\t%w0, %w3, %w1, <shift> %2"
1334   [(set_attr "v8type" "alu_shift")
1335    (set_attr "mode" "SI")]
1336 )
1337
1338 (define_insn "*add_mul_imm_<mode>"
1339   [(set (match_operand:GPI 0 "register_operand" "=rk")
1340         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1341                             (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1342                   (match_operand:GPI 3 "register_operand" "r")))]
1343   ""
1344   "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1345   [(set_attr "v8type" "alu_shift")
1346    (set_attr "mode" "<MODE>")]
1347 )
1348
1349 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
1350   [(set (match_operand:GPI 0 "register_operand" "=rk")
1351         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1352                   (match_operand:GPI 2 "register_operand" "r")))]
1353   ""
1354   "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1355   [(set_attr "v8type" "alu_ext")
1356    (set_attr "mode" "<GPI:MODE>")]
1357 )
1358
1359 ;; zero_extend version of above
1360 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
1361   [(set (match_operand:DI 0 "register_operand" "=rk")
1362         (zero_extend:DI
1363          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
1364                   (match_operand:GPI 2 "register_operand" "r"))))]
1365   ""
1366   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
1367   [(set_attr "v8type" "alu_ext")
1368    (set_attr "mode" "SI")]
1369 )
1370
1371 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
1372   [(set (match_operand:GPI 0 "register_operand" "=rk")
1373         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
1374                                (match_operand:ALLX 1 "register_operand" "r"))
1375                               (match_operand 2 "aarch64_imm3" "Ui3"))
1376                   (match_operand:GPI 3 "register_operand" "r")))]
1377   ""
1378   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1379   [(set_attr "v8type" "alu_ext")
1380    (set_attr "mode" "<GPI:MODE>")]
1381 )
1382
1383 ;; zero_extend version of above
1384 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
1385   [(set (match_operand:DI 0 "register_operand" "=rk")
1386         (zero_extend:DI
1387          (plus:SI (ashift:SI (ANY_EXTEND:SI
1388                               (match_operand:SHORT 1 "register_operand" "r"))
1389                              (match_operand 2 "aarch64_imm3" "Ui3"))
1390                   (match_operand:SI 3 "register_operand" "r"))))]
1391   ""
1392   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
1393   [(set_attr "v8type" "alu_ext")
1394    (set_attr "mode" "SI")]
1395 )
1396
1397 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
1398   [(set (match_operand:GPI 0 "register_operand" "=rk")
1399         (plus:GPI (mult:GPI (ANY_EXTEND:GPI
1400                              (match_operand:ALLX 1 "register_operand" "r"))
1401                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1402                   (match_operand:GPI 3 "register_operand" "r")))]
1403   ""
1404   "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
1405   [(set_attr "v8type" "alu_ext")
1406    (set_attr "mode" "<GPI:MODE>")]
1407 )
1408
1409 ;; zero_extend version of above
1410 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
1411   [(set (match_operand:DI 0 "register_operand" "=rk")
1412         (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
1413                              (match_operand:SHORT 1 "register_operand" "r"))
1414                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1415                   (match_operand:SI 3 "register_operand" "r"))))]
1416   ""
1417   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
1418   [(set_attr "v8type" "alu_ext")
1419    (set_attr "mode" "SI")]
1420 )
1421
1422 (define_insn "*add_<optab><mode>_multp2"
1423   [(set (match_operand:GPI 0 "register_operand" "=rk")
1424         (plus:GPI (ANY_EXTRACT:GPI
1425                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1426                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1427                    (match_operand 3 "const_int_operand" "n")
1428                    (const_int 0))
1429                   (match_operand:GPI 4 "register_operand" "r")))]
1430   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1431   "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1432   [(set_attr "v8type" "alu_ext")
1433    (set_attr "mode" "<MODE>")]
1434 )
1435
1436 ;; zero_extend version of above
1437 (define_insn "*add_<optab>si_multp2_uxtw"
1438   [(set (match_operand:DI 0 "register_operand" "=rk")
1439         (zero_extend:DI
1440          (plus:SI (ANY_EXTRACT:SI
1441                    (mult:SI (match_operand:SI 1 "register_operand" "r")
1442                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1443                    (match_operand 3 "const_int_operand" "n")
1444                    (const_int 0))
1445                   (match_operand:SI 4 "register_operand" "r"))))]
1446   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
1447   "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
1448   [(set_attr "v8type" "alu_ext")
1449    (set_attr "mode" "SI")]
1450 )
1451
1452 (define_insn "*add<mode>3_carryin"
1453   [(set
1454     (match_operand:GPI 0 "register_operand" "=r")
1455     (plus:GPI (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1456               (plus:GPI
1457                 (match_operand:GPI 1 "register_operand" "r")
1458                 (match_operand:GPI 2 "register_operand" "r"))))]
1459    ""
1460    "adc\\t%<w>0, %<w>1, %<w>2"
1461   [(set_attr "v8type" "adc")
1462    (set_attr "mode" "<MODE>")]
1463 )
1464
1465 ;; zero_extend version of above
1466 (define_insn "*addsi3_carryin_uxtw"
1467   [(set
1468     (match_operand:DI 0 "register_operand" "=r")
1469     (zero_extend:DI
1470      (plus:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
1471               (plus:SI
1472                (match_operand:SI 1 "register_operand" "r")
1473                (match_operand:SI 2 "register_operand" "r")))))]
1474    ""
1475    "adc\\t%w0, %w1, %w2"
1476   [(set_attr "v8type" "adc")
1477    (set_attr "mode" "SI")]
1478 )
1479
1480 (define_insn "*add<mode>3_carryin_alt1"
1481   [(set
1482     (match_operand:GPI 0 "register_operand" "=r")
1483     (plus:GPI (plus:GPI
1484                 (match_operand:GPI 1 "register_operand" "r")
1485                 (match_operand:GPI 2 "register_operand" "r"))
1486               (geu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
1487    ""
1488    "adc\\t%<w>0, %<w>1, %<w>2"
1489   [(set_attr "v8type" "adc")
1490    (set_attr "mode" "<MODE>")]
1491 )
1492
1493 ;; zero_extend version of above
1494 (define_insn "*addsi3_carryin_alt1_uxtw"
1495   [(set
1496     (match_operand:DI 0 "register_operand" "=r")
1497     (zero_extend:DI
1498      (plus:SI (plus:SI
1499                (match_operand:SI 1 "register_operand" "r")
1500                (match_operand:SI 2 "register_operand" "r"))
1501               (geu:SI (reg:CC CC_REGNUM) (const_int 0)))))]
1502    ""
1503    "adc\\t%w0, %w1, %w2"
1504   [(set_attr "v8type" "adc")
1505    (set_attr "mode" "SI")]
1506 )
1507
1508 (define_insn "*add<mode>3_carryin_alt2"
1509   [(set
1510     (match_operand:GPI 0 "register_operand" "=r")
1511     (plus:GPI (plus:GPI
1512                 (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1513                 (match_operand:GPI 1 "register_operand" "r"))
1514               (match_operand:GPI 2 "register_operand" "r")))]
1515    ""
1516    "adc\\t%<w>0, %<w>1, %<w>2"
1517   [(set_attr "v8type" "adc")
1518    (set_attr "mode" "<MODE>")]
1519 )
1520
1521 ;; zero_extend version of above
1522 (define_insn "*addsi3_carryin_alt2_uxtw"
1523   [(set
1524     (match_operand:DI 0 "register_operand" "=r")
1525     (zero_extend:DI
1526      (plus:SI (plus:SI
1527                (geu:SI (reg:CC CC_REGNUM) (const_int 0))
1528                (match_operand:SI 1 "register_operand" "r"))
1529               (match_operand:SI 2 "register_operand" "r"))))]
1530    ""
1531    "adc\\t%w0, %w1, %w2"
1532   [(set_attr "v8type" "adc")
1533    (set_attr "mode" "SI")]
1534 )
1535
1536 (define_insn "*add<mode>3_carryin_alt3"
1537   [(set
1538     (match_operand:GPI 0 "register_operand" "=r")
1539     (plus:GPI (plus:GPI
1540                 (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
1541                 (match_operand:GPI 2 "register_operand" "r"))
1542               (match_operand:GPI 1 "register_operand" "r")))]
1543    ""
1544    "adc\\t%<w>0, %<w>1, %<w>2"
1545   [(set_attr "v8type" "adc")
1546    (set_attr "mode" "<MODE>")]
1547 )
1548
1549 ;; zero_extend version of above
1550 (define_insn "*addsi3_carryin_alt3_uxtw"
1551   [(set
1552     (match_operand:DI 0 "register_operand" "=r")
1553     (zero_extend:DI
1554      (plus:SI (plus:SI
1555                (geu:SI (reg:CC CC_REGNUM) (const_int 0))
1556                (match_operand:SI 2 "register_operand" "r"))
1557               (match_operand:SI 1 "register_operand" "r"))))]
1558    ""
1559    "adc\\t%w0, %w1, %w2"
1560   [(set_attr "v8type" "adc")
1561    (set_attr "mode" "SI")]
1562 )
1563
1564 (define_insn "*add_uxt<mode>_multp2"
1565   [(set (match_operand:GPI 0 "register_operand" "=rk")
1566         (plus:GPI (and:GPI
1567                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1568                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1569                    (match_operand 3 "const_int_operand" "n"))
1570                   (match_operand:GPI 4 "register_operand" "r")))]
1571   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
1572   "*
1573   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1574                                            INTVAL (operands[3])));
1575   return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
1576   [(set_attr "v8type" "alu_ext")
1577    (set_attr "mode" "<MODE>")]
1578 )
1579
1580 ;; zero_extend version of above
1581 (define_insn "*add_uxtsi_multp2_uxtw"
1582   [(set (match_operand:DI 0 "register_operand" "=rk")
1583         (zero_extend:DI
1584          (plus:SI (and:SI
1585                    (mult:SI (match_operand:SI 1 "register_operand" "r")
1586                             (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1587                    (match_operand 3 "const_int_operand" "n"))
1588                   (match_operand:SI 4 "register_operand" "r"))))]
1589   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
1590   "*
1591   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1592                                            INTVAL (operands[3])));
1593   return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
1594   [(set_attr "v8type" "alu_ext")
1595    (set_attr "mode" "SI")]
1596 )
1597
1598 (define_insn "subsi3"
1599   [(set (match_operand:SI 0 "register_operand" "=rk")
1600         (minus:SI (match_operand:SI 1 "register_operand" "r")
1601                    (match_operand:SI 2 "register_operand" "r")))]
1602   ""
1603   "sub\\t%w0, %w1, %w2"
1604   [(set_attr "v8type" "alu")
1605    (set_attr "mode" "SI")]
1606 )
1607
1608 ;; zero_extend version of above
1609 (define_insn "*subsi3_uxtw"
1610   [(set (match_operand:DI 0 "register_operand" "=rk")
1611         (zero_extend:DI
1612          (minus:SI (match_operand:SI 1 "register_operand" "r")
1613                    (match_operand:SI 2 "register_operand" "r"))))]
1614   ""
1615   "sub\\t%w0, %w1, %w2"
1616   [(set_attr "v8type" "alu")
1617    (set_attr "mode" "SI")]
1618 )
1619
1620 (define_insn "subdi3"
1621   [(set (match_operand:DI 0 "register_operand" "=rk,!w")
1622         (minus:DI (match_operand:DI 1 "register_operand" "r,!w")
1623                    (match_operand:DI 2 "register_operand" "r,!w")))]
1624   ""
1625   "@
1626    sub\\t%x0, %x1, %x2
1627    sub\\t%d0, %d1, %d2"
1628   [(set_attr "v8type" "alu")
1629    (set_attr "mode" "DI")
1630    (set_attr "simd" "*,yes")]
1631 )
1632
1633
1634 (define_insn "*sub<mode>3_compare0"
1635   [(set (reg:CC_NZ CC_REGNUM)
1636         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1637                                   (match_operand:GPI 2 "register_operand" "r"))
1638                        (const_int 0)))
1639    (set (match_operand:GPI 0 "register_operand" "=r")
1640         (minus:GPI (match_dup 1) (match_dup 2)))]
1641   ""
1642   "subs\\t%<w>0, %<w>1, %<w>2"
1643   [(set_attr "v8type" "alus")
1644    (set_attr "mode" "<MODE>")]
1645 )
1646
1647 ;; zero_extend version of above
1648 (define_insn "*subsi3_compare0_uxtw"
1649   [(set (reg:CC_NZ CC_REGNUM)
1650         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
1651                                  (match_operand:SI 2 "register_operand" "r"))
1652                        (const_int 0)))
1653    (set (match_operand:DI 0 "register_operand" "=r")
1654         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
1655   ""
1656   "subs\\t%w0, %w1, %w2"
1657   [(set_attr "v8type" "alus")
1658    (set_attr "mode" "SI")]
1659 )
1660
1661 (define_insn "*sub_<shift>_<mode>"
1662   [(set (match_operand:GPI 0 "register_operand" "=rk")
1663         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
1664                    (ASHIFT:GPI
1665                     (match_operand:GPI 1 "register_operand" "r")
1666                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
1667   ""
1668   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1669   [(set_attr "v8type" "alu_shift")
1670    (set_attr "mode" "<MODE>")]
1671 )
1672
1673 ;; zero_extend version of above
1674 (define_insn "*sub_<shift>_si_uxtw"
1675   [(set (match_operand:DI 0 "register_operand" "=rk")
1676         (zero_extend:DI
1677          (minus:SI (match_operand:SI 3 "register_operand" "r")
1678                    (ASHIFT:SI
1679                     (match_operand:SI 1 "register_operand" "r")
1680                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
1681   ""
1682   "sub\\t%w0, %w3, %w1, <shift> %2"
1683   [(set_attr "v8type" "alu_shift")
1684    (set_attr "mode" "SI")]
1685 )
1686
1687 (define_insn "*sub_mul_imm_<mode>"
1688   [(set (match_operand:GPI 0 "register_operand" "=rk")
1689         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
1690                    (mult:GPI
1691                     (match_operand:GPI 1 "register_operand" "r")
1692                     (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
1693   ""
1694   "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1695   [(set_attr "v8type" "alu_shift")
1696    (set_attr "mode" "<MODE>")]
1697 )
1698
1699 ;; zero_extend version of above
1700 (define_insn "*sub_mul_imm_si_uxtw"
1701   [(set (match_operand:DI 0 "register_operand" "=rk")
1702         (zero_extend:DI
1703          (minus:SI (match_operand:SI 3 "register_operand" "r")
1704                    (mult:SI
1705                     (match_operand:SI 1 "register_operand" "r")
1706                     (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
1707   ""
1708   "sub\\t%w0, %w3, %w1, lsl %p2"
1709   [(set_attr "v8type" "alu_shift")
1710    (set_attr "mode" "SI")]
1711 )
1712
1713 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
1714   [(set (match_operand:GPI 0 "register_operand" "=rk")
1715         (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1716                    (ANY_EXTEND:GPI
1717                     (match_operand:ALLX 2 "register_operand" "r"))))]
1718   ""
1719   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1720   [(set_attr "v8type" "alu_ext")
1721    (set_attr "mode" "<GPI:MODE>")]
1722 )
1723
1724 ;; zero_extend version of above
1725 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
1726   [(set (match_operand:DI 0 "register_operand" "=rk")
1727         (zero_extend:DI
1728          (minus:SI (match_operand:SI 1 "register_operand" "r")
1729                    (ANY_EXTEND:SI
1730                     (match_operand:SHORT 2 "register_operand" "r")))))]
1731   ""
1732   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
1733   [(set_attr "v8type" "alu_ext")
1734    (set_attr "mode" "SI")]
1735 )
1736
1737 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
1738   [(set (match_operand:GPI 0 "register_operand" "=rk")
1739         (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1740                    (ashift:GPI (ANY_EXTEND:GPI
1741                                 (match_operand:ALLX 2 "register_operand" "r"))
1742                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
1743   ""
1744   "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1745   [(set_attr "v8type" "alu_ext")
1746    (set_attr "mode" "<GPI:MODE>")]
1747 )
1748
1749 ;; zero_extend version of above
1750 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
1751   [(set (match_operand:DI 0 "register_operand" "=rk")
1752         (zero_extend:DI
1753          (minus:SI (match_operand:SI 1 "register_operand" "r")
1754                    (ashift:SI (ANY_EXTEND:SI
1755                                (match_operand:SHORT 2 "register_operand" "r"))
1756                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
1757   ""
1758   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
1759   [(set_attr "v8type" "alu_ext")
1760    (set_attr "mode" "SI")]
1761 )
1762
1763 (define_insn "*sub_<optab><mode>_multp2"
1764   [(set (match_operand:GPI 0 "register_operand" "=rk")
1765         (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1766                    (ANY_EXTRACT:GPI
1767                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1768                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1769                     (match_operand 3 "const_int_operand" "n")
1770                     (const_int 0))))]
1771   "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1772   "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1773   [(set_attr "v8type" "alu_ext")
1774    (set_attr "mode" "<MODE>")]
1775 )
1776
1777 ;; zero_extend version of above
1778 (define_insn "*sub_<optab>si_multp2_uxtw"
1779   [(set (match_operand:DI 0 "register_operand" "=rk")
1780         (zero_extend:DI
1781          (minus:SI (match_operand:SI 4 "register_operand" "r")
1782                    (ANY_EXTRACT:SI
1783                     (mult:SI (match_operand:SI 1 "register_operand" "r")
1784                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1785                     (match_operand 3 "const_int_operand" "n")
1786                     (const_int 0)))))]
1787   "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
1788   "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
1789   [(set_attr "v8type" "alu_ext")
1790    (set_attr "mode" "SI")]
1791 )
1792
1793 (define_insn "*sub_uxt<mode>_multp2"
1794   [(set (match_operand:GPI 0 "register_operand" "=rk")
1795         (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1796                    (and:GPI
1797                     (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1798                               (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1799                     (match_operand 3 "const_int_operand" "n"))))]
1800   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
1801   "*
1802   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1803                                            INTVAL (operands[3])));
1804   return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
1805   [(set_attr "v8type" "alu_ext")
1806    (set_attr "mode" "<MODE>")]
1807 )
1808
1809 ;; zero_extend version of above
1810 (define_insn "*sub_uxtsi_multp2_uxtw"
1811   [(set (match_operand:DI 0 "register_operand" "=rk")
1812         (zero_extend:DI
1813          (minus:SI (match_operand:SI 4 "register_operand" "r")
1814                    (and:SI
1815                     (mult:SI (match_operand:SI 1 "register_operand" "r")
1816                              (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1817                     (match_operand 3 "const_int_operand" "n")))))]
1818   "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
1819   "*
1820   operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
1821                                            INTVAL (operands[3])));
1822   return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
1823   [(set_attr "v8type" "alu_ext")
1824    (set_attr "mode" "SI")]
1825 )
1826
1827 (define_insn "neg<mode>2"
1828   [(set (match_operand:GPI 0 "register_operand" "=r")
1829         (neg:GPI (match_operand:GPI 1 "register_operand" "r")))]
1830   ""
1831   "neg\\t%<w>0, %<w>1"
1832   [(set_attr "v8type" "alu")
1833    (set_attr "mode" "<MODE>")]
1834 )
1835
1836 ;; zero_extend version of above
1837 (define_insn "*negsi2_uxtw"
1838   [(set (match_operand:DI 0 "register_operand" "=r")
1839         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
1840   ""
1841   "neg\\t%w0, %w1"
1842   [(set_attr "v8type" "alu")
1843    (set_attr "mode" "SI")]
1844 )
1845
1846 (define_insn "*neg<mode>2_compare0"
1847   [(set (reg:CC_NZ CC_REGNUM)
1848         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
1849                        (const_int 0)))
1850    (set (match_operand:GPI 0 "register_operand" "=r")
1851         (neg:GPI (match_dup 1)))]
1852   ""
1853   "negs\\t%<w>0, %<w>1"
1854   [(set_attr "v8type" "alus")
1855    (set_attr "mode" "<MODE>")]
1856 )
1857
1858 ;; zero_extend version of above
1859 (define_insn "*negsi2_compare0_uxtw"
1860   [(set (reg:CC_NZ CC_REGNUM)
1861         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
1862                        (const_int 0)))
1863    (set (match_operand:DI 0 "register_operand" "=r")
1864         (zero_extend:DI (neg:SI (match_dup 1))))]
1865   ""
1866   "negs\\t%w0, %w1"
1867   [(set_attr "v8type" "alus")
1868    (set_attr "mode" "SI")]
1869 )
1870
1871 (define_insn "*neg_<shift>_<mode>2"
1872   [(set (match_operand:GPI 0 "register_operand" "=r")
1873         (neg:GPI (ASHIFT:GPI
1874                   (match_operand:GPI 1 "register_operand" "r")
1875                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
1876   ""
1877   "neg\\t%<w>0, %<w>1, <shift> %2"
1878   [(set_attr "v8type" "alu_shift")
1879    (set_attr "mode" "<MODE>")]
1880 )
1881
1882 ;; zero_extend version of above
1883 (define_insn "*neg_<shift>_si2_uxtw"
1884   [(set (match_operand:DI 0 "register_operand" "=r")
1885         (zero_extend:DI
1886          (neg:SI (ASHIFT:SI
1887                   (match_operand:SI 1 "register_operand" "r")
1888                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
1889   ""
1890   "neg\\t%w0, %w1, <shift> %2"
1891   [(set_attr "v8type" "alu_shift")
1892    (set_attr "mode" "SI")]
1893 )
1894
1895 (define_insn "*neg_mul_imm_<mode>2"
1896   [(set (match_operand:GPI 0 "register_operand" "=r")
1897         (neg:GPI (mult:GPI
1898                   (match_operand:GPI 1 "register_operand" "r")
1899                   (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
1900   ""
1901   "neg\\t%<w>0, %<w>1, lsl %p2"
1902   [(set_attr "v8type" "alu_shift")
1903    (set_attr "mode" "<MODE>")]
1904 )
1905
1906 ;; zero_extend version of above
1907 (define_insn "*neg_mul_imm_si2_uxtw"
1908   [(set (match_operand:DI 0 "register_operand" "=r")
1909         (zero_extend:DI
1910          (neg:SI (mult:SI
1911                   (match_operand:SI 1 "register_operand" "r")
1912                   (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
1913   ""
1914   "neg\\t%w0, %w1, lsl %p2"
1915   [(set_attr "v8type" "alu_shift")
1916    (set_attr "mode" "SI")]
1917 )
1918
1919 (define_insn "mul<mode>3"
1920   [(set (match_operand:GPI 0 "register_operand" "=r")
1921         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1922                   (match_operand:GPI 2 "register_operand" "r")))]
1923   ""
1924   "mul\\t%<w>0, %<w>1, %<w>2"
1925   [(set_attr "v8type" "mult")
1926    (set_attr "mode" "<MODE>")]
1927 )
1928
1929 ;; zero_extend version of above
1930 (define_insn "*mulsi3_uxtw"
1931   [(set (match_operand:DI 0 "register_operand" "=r")
1932         (zero_extend:DI
1933          (mult:SI (match_operand:SI 1 "register_operand" "r")
1934                   (match_operand:SI 2 "register_operand" "r"))))]
1935   ""
1936   "mul\\t%w0, %w1, %w2"
1937   [(set_attr "v8type" "mult")
1938    (set_attr "mode" "SI")]
1939 )
1940
1941 (define_insn "*madd<mode>"
1942   [(set (match_operand:GPI 0 "register_operand" "=r")
1943         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1944                             (match_operand:GPI 2 "register_operand" "r"))
1945                   (match_operand:GPI 3 "register_operand" "r")))]
1946   ""
1947   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
1948   [(set_attr "v8type" "madd")
1949    (set_attr "mode" "<MODE>")]
1950 )
1951
1952 ;; zero_extend version of above
1953 (define_insn "*maddsi_uxtw"
1954   [(set (match_operand:DI 0 "register_operand" "=r")
1955         (zero_extend:DI
1956          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
1957                            (match_operand:SI 2 "register_operand" "r"))
1958                   (match_operand:SI 3 "register_operand" "r"))))]
1959   ""
1960   "madd\\t%w0, %w1, %w2, %w3"
1961   [(set_attr "v8type" "madd")
1962    (set_attr "mode" "SI")]
1963 )
1964
1965 (define_insn "*msub<mode>"
1966   [(set (match_operand:GPI 0 "register_operand" "=r")
1967         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
1968                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1969                              (match_operand:GPI 2 "register_operand" "r"))))]
1970
1971   ""
1972   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
1973   [(set_attr "v8type" "madd")
1974    (set_attr "mode" "<MODE>")]
1975 )
1976
1977 ;; zero_extend version of above
1978 (define_insn "*msubsi_uxtw"
1979   [(set (match_operand:DI 0 "register_operand" "=r")
1980         (zero_extend:DI
1981          (minus:SI (match_operand:SI 3 "register_operand" "r")
1982                    (mult:SI (match_operand:SI 1 "register_operand" "r")
1983                             (match_operand:SI 2 "register_operand" "r")))))]
1984
1985   ""
1986   "msub\\t%w0, %w1, %w2, %w3"
1987   [(set_attr "v8type" "madd")
1988    (set_attr "mode" "SI")]
1989 )
1990
1991 (define_insn "*mul<mode>_neg"
1992   [(set (match_operand:GPI 0 "register_operand" "=r")
1993         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
1994                   (match_operand:GPI 2 "register_operand" "r")))]
1995
1996   ""
1997   "mneg\\t%<w>0, %<w>1, %<w>2"
1998   [(set_attr "v8type" "mult")
1999    (set_attr "mode" "<MODE>")]
2000 )
2001
2002 ;; zero_extend version of above
2003 (define_insn "*mulsi_neg_uxtw"
2004   [(set (match_operand:DI 0 "register_operand" "=r")
2005         (zero_extend:DI
2006          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2007                   (match_operand:SI 2 "register_operand" "r"))))]
2008
2009   ""
2010   "mneg\\t%w0, %w1, %w2"
2011   [(set_attr "v8type" "mult")
2012    (set_attr "mode" "SI")]
2013 )
2014
2015 (define_insn "<su_optab>mulsidi3"
2016   [(set (match_operand:DI 0 "register_operand" "=r")
2017         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2018                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2019   ""
2020   "<su>mull\\t%0, %w1, %w2"
2021   [(set_attr "v8type" "mull")
2022    (set_attr "mode" "DI")]
2023 )
2024
2025 (define_insn "<su_optab>maddsidi4"
2026   [(set (match_operand:DI 0 "register_operand" "=r")
2027         (plus:DI (mult:DI
2028                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2029                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2030                  (match_operand:DI 3 "register_operand" "r")))]
2031   ""
2032   "<su>maddl\\t%0, %w1, %w2, %3"
2033   [(set_attr "v8type" "maddl")
2034    (set_attr "mode" "DI")]
2035 )
2036
2037 (define_insn "<su_optab>msubsidi4"
2038   [(set (match_operand:DI 0 "register_operand" "=r")
2039         (minus:DI
2040          (match_operand:DI 3 "register_operand" "r")
2041          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2042                   (ANY_EXTEND:DI
2043                    (match_operand:SI 2 "register_operand" "r")))))]
2044   ""
2045   "<su>msubl\\t%0, %w1, %w2, %3"
2046   [(set_attr "v8type" "maddl")
2047    (set_attr "mode" "DI")]
2048 )
2049
2050 (define_insn "*<su_optab>mulsidi_neg"
2051   [(set (match_operand:DI 0 "register_operand" "=r")
2052         (mult:DI (neg:DI
2053                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2054                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2055   ""
2056   "<su>mnegl\\t%0, %w1, %w2"
2057   [(set_attr "v8type" "mull")
2058    (set_attr "mode" "DI")]
2059 )
2060
2061 (define_insn "<su>muldi3_highpart"
2062   [(set (match_operand:DI 0 "register_operand" "=r")
2063         (truncate:DI
2064          (lshiftrt:TI
2065           (mult:TI
2066            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
2067            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
2068           (const_int 64))))]
2069   ""
2070   "<su>mulh\\t%0, %1, %2"
2071   [(set_attr "v8type" "mulh")
2072    (set_attr "mode" "DI")]
2073 )
2074
2075 (define_insn "<su_optab>div<mode>3"
2076   [(set (match_operand:GPI 0 "register_operand" "=r")
2077         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
2078                      (match_operand:GPI 2 "register_operand" "r")))]
2079   ""
2080   "<su>div\\t%<w>0, %<w>1, %<w>2"
2081   [(set_attr "v8type" "<su>div")
2082    (set_attr "mode" "<MODE>")]
2083 )
2084
2085 ;; zero_extend version of above
2086 (define_insn "*<su_optab>divsi3_uxtw"
2087   [(set (match_operand:DI 0 "register_operand" "=r")
2088         (zero_extend:DI
2089          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
2090                      (match_operand:SI 2 "register_operand" "r"))))]
2091   ""
2092   "<su>div\\t%w0, %w1, %w2"
2093   [(set_attr "v8type" "<su>div")
2094    (set_attr "mode" "SI")]
2095 )
2096
2097 ;; -------------------------------------------------------------------
2098 ;; Comparison insns
2099 ;; -------------------------------------------------------------------
2100
2101 (define_insn "*cmp<mode>"
2102   [(set (reg:CC CC_REGNUM)
2103         (compare:CC (match_operand:GPI 0 "register_operand" "r,r")
2104                     (match_operand:GPI 1 "aarch64_plus_operand" "rI,J")))]
2105   ""
2106   "@
2107    cmp\\t%<w>0, %<w>1
2108    cmn\\t%<w>0, #%n1"
2109   [(set_attr "v8type" "alus")
2110    (set_attr "mode" "<MODE>")]
2111 )
2112
2113 (define_insn "*cmp<mode>"
2114   [(set (reg:CCFP CC_REGNUM)
2115         (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
2116                       (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2117    "TARGET_FLOAT"
2118    "@
2119     fcmp\\t%<s>0, #0.0
2120     fcmp\\t%<s>0, %<s>1"
2121   [(set_attr "v8type" "fcmp")
2122    (set_attr "mode" "<MODE>")]
2123 )
2124
2125 (define_insn "*cmpe<mode>"
2126   [(set (reg:CCFPE CC_REGNUM)
2127         (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
2128                        (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
2129    "TARGET_FLOAT"
2130    "@
2131     fcmpe\\t%<s>0, #0.0
2132     fcmpe\\t%<s>0, %<s>1"
2133   [(set_attr "v8type" "fcmp")
2134    (set_attr "mode" "<MODE>")]
2135 )
2136
2137 (define_insn "*cmp_swp_<shift>_reg<mode>"
2138   [(set (reg:CC_SWP CC_REGNUM)
2139         (compare:CC_SWP (ASHIFT:GPI
2140                          (match_operand:GPI 0 "register_operand" "r")
2141                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2142                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
2143   ""
2144   "cmp\\t%<w>2, %<w>0, <shift> %1"
2145   [(set_attr "v8type" "alus_shift")
2146    (set_attr "mode" "<MODE>")]
2147 )
2148
2149 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
2150   [(set (reg:CC_SWP CC_REGNUM)
2151         (compare:CC_SWP (ANY_EXTEND:GPI
2152                          (match_operand:ALLX 0 "register_operand" "r"))
2153                         (match_operand:GPI 1 "register_operand" "r")))]
2154   ""
2155   "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
2156   [(set_attr "v8type" "alus_ext")
2157    (set_attr "mode" "<GPI:MODE>")]
2158 )
2159
2160
2161 ;; -------------------------------------------------------------------
2162 ;; Store-flag and conditional select insns
2163 ;; -------------------------------------------------------------------
2164
2165 (define_expand "cstore<mode>4"
2166   [(set (match_operand:SI 0 "register_operand" "")
2167         (match_operator:SI 1 "aarch64_comparison_operator"
2168          [(match_operand:GPI 2 "register_operand" "")
2169           (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
2170   ""
2171   "
2172   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2173                                       operands[3]);
2174   operands[3] = const0_rtx;
2175   "
2176 )
2177
2178 (define_expand "cstore<mode>4"
2179   [(set (match_operand:SI 0 "register_operand" "")
2180         (match_operator:SI 1 "aarch64_comparison_operator"
2181          [(match_operand:GPF 2 "register_operand" "")
2182           (match_operand:GPF 3 "register_operand" "")]))]
2183   ""
2184   "
2185   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2186                                       operands[3]);
2187   operands[3] = const0_rtx;
2188   "
2189 )
2190
2191 (define_insn "*cstore<mode>_insn"
2192   [(set (match_operand:ALLI 0 "register_operand" "=r")
2193         (match_operator:ALLI 1 "aarch64_comparison_operator"
2194          [(match_operand 2 "cc_register" "") (const_int 0)]))]
2195   ""
2196   "cset\\t%<w>0, %m1"
2197   [(set_attr "v8type" "csel")
2198    (set_attr "mode" "<MODE>")]
2199 )
2200
2201 ;; zero_extend version of the above
2202 (define_insn "*cstoresi_insn_uxtw"
2203   [(set (match_operand:DI 0 "register_operand" "=r")
2204         (zero_extend:DI
2205          (match_operator:SI 1 "aarch64_comparison_operator"
2206           [(match_operand 2 "cc_register" "") (const_int 0)])))]
2207   ""
2208   "cset\\t%w0, %m1"
2209   [(set_attr "v8type" "csel")
2210    (set_attr "mode" "SI")]
2211 )
2212
2213 (define_insn "*cstore<mode>_neg"
2214   [(set (match_operand:ALLI 0 "register_operand" "=r")
2215         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator"
2216                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
2217   ""
2218   "csetm\\t%<w>0, %m1"
2219   [(set_attr "v8type" "csel")
2220    (set_attr "mode" "<MODE>")]
2221 )
2222
2223 ;; zero_extend version of the above
2224 (define_insn "*cstoresi_neg_uxtw"
2225   [(set (match_operand:DI 0 "register_operand" "=r")
2226         (zero_extend:DI
2227          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator"
2228                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
2229   ""
2230   "csetm\\t%w0, %m1"
2231   [(set_attr "v8type" "csel")
2232    (set_attr "mode" "SI")]
2233 )
2234
2235 (define_expand "cmov<mode>6"
2236   [(set (match_operand:GPI 0 "register_operand" "")
2237         (if_then_else:GPI
2238          (match_operator 1 "aarch64_comparison_operator"
2239           [(match_operand:GPI 2 "register_operand" "")
2240            (match_operand:GPI 3 "aarch64_plus_operand" "")])
2241          (match_operand:GPI 4 "register_operand" "")
2242          (match_operand:GPI 5 "register_operand" "")))]
2243   ""
2244   "
2245   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2246                                       operands[3]);
2247   operands[3] = const0_rtx;
2248   "
2249 )
2250
2251 (define_expand "cmov<mode>6"
2252   [(set (match_operand:GPF 0 "register_operand" "")
2253         (if_then_else:GPF
2254          (match_operator 1 "aarch64_comparison_operator"
2255           [(match_operand:GPF 2 "register_operand" "")
2256            (match_operand:GPF 3 "register_operand" "")])
2257          (match_operand:GPF 4 "register_operand" "")
2258          (match_operand:GPF 5 "register_operand" "")))]
2259   ""
2260   "
2261   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
2262                                       operands[3]);
2263   operands[3] = const0_rtx;
2264   "
2265 )
2266
2267 (define_insn "*cmov<mode>_insn"
2268   [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
2269         (if_then_else:ALLI
2270          (match_operator 1 "aarch64_comparison_operator"
2271           [(match_operand 2 "cc_register" "") (const_int 0)])
2272          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
2273          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
2274   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
2275      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
2276   ;; Final two alternatives should be unreachable, but included for completeness
2277   "@
2278    csel\\t%<w>0, %<w>3, %<w>4, %m1
2279    csinv\\t%<w>0, %<w>3, <w>zr, %m1
2280    csinv\\t%<w>0, %<w>4, <w>zr, %M1
2281    csinc\\t%<w>0, %<w>3, <w>zr, %m1
2282    csinc\\t%<w>0, %<w>4, <w>zr, %M1
2283    mov\\t%<w>0, -1
2284    mov\\t%<w>0, 1"
2285   [(set_attr "v8type" "csel")
2286    (set_attr "mode" "<MODE>")]
2287 )
2288
2289 ;; zero_extend version of above
2290 (define_insn "*cmovsi_insn_uxtw"
2291   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
2292         (zero_extend:DI
2293          (if_then_else:SI
2294           (match_operator 1 "aarch64_comparison_operator"
2295            [(match_operand 2 "cc_register" "") (const_int 0)])
2296           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
2297           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
2298   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
2299      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
2300   ;; Final two alternatives should be unreachable, but included for completeness
2301   "@
2302    csel\\t%w0, %w3, %w4, %m1
2303    csinv\\t%w0, %w3, wzr, %m1
2304    csinv\\t%w0, %w4, wzr, %M1
2305    csinc\\t%w0, %w3, wzr, %m1
2306    csinc\\t%w0, %w4, wzr, %M1
2307    mov\\t%w0, -1
2308    mov\\t%w0, 1"
2309   [(set_attr "v8type" "csel")
2310    (set_attr "mode" "SI")]
2311 )
2312
2313 (define_insn "*cmov<mode>_insn"
2314   [(set (match_operand:GPF 0 "register_operand" "=w")
2315         (if_then_else:GPF
2316          (match_operator 1 "aarch64_comparison_operator"
2317           [(match_operand 2 "cc_register" "") (const_int 0)])
2318          (match_operand:GPF 3 "register_operand" "w")
2319          (match_operand:GPF 4 "register_operand" "w")))]
2320   "TARGET_FLOAT"
2321   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
2322   [(set_attr "v8type" "fcsel")
2323    (set_attr "mode" "<MODE>")]
2324 )
2325
2326 (define_expand "mov<mode>cc"
2327   [(set (match_operand:ALLI 0 "register_operand" "")
2328         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
2329                            (match_operand:ALLI 2 "register_operand" "")
2330                            (match_operand:ALLI 3 "register_operand" "")))]
2331   ""
2332   {
2333     rtx ccreg;
2334     enum rtx_code code = GET_CODE (operands[1]);
2335
2336     if (code == UNEQ || code == LTGT)
2337       FAIL;
2338
2339     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
2340                                   XEXP (operands[1], 1));
2341     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
2342   }
2343 )
2344
2345 (define_expand "mov<GPF:mode><GPI:mode>cc"
2346   [(set (match_operand:GPI 0 "register_operand" "")
2347         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
2348                           (match_operand:GPF 2 "register_operand" "")
2349                           (match_operand:GPF 3 "register_operand" "")))]
2350   ""
2351   {
2352     rtx ccreg;
2353     enum rtx_code code = GET_CODE (operands[1]);
2354
2355     if (code == UNEQ || code == LTGT)
2356       FAIL;
2357
2358     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
2359                                   XEXP (operands[1], 1));
2360     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
2361   }
2362 )
2363
2364 (define_insn "*csinc2<mode>_insn"
2365   [(set (match_operand:GPI 0 "register_operand" "=r")
2366         (plus:GPI (match_operator:GPI 2 "aarch64_comparison_operator"
2367                   [(match_operand:CC 3 "cc_register" "") (const_int 0)])
2368                  (match_operand:GPI 1 "register_operand" "r")))]
2369   ""
2370   "csinc\\t%<w>0, %<w>1, %<w>1, %M2"
2371   [(set_attr "v8type" "csel")
2372    (set_attr "mode" "<MODE>")])
2373
2374 (define_insn "csinc3<mode>_insn"
2375   [(set (match_operand:GPI 0 "register_operand" "=r")
2376         (if_then_else:GPI
2377           (match_operator:GPI 1 "aarch64_comparison_operator"
2378            [(match_operand:CC 2 "cc_register" "") (const_int 0)])
2379           (plus:GPI (match_operand:GPI 3 "register_operand" "r")
2380                     (const_int 1))
2381           (match_operand:GPI 4 "aarch64_reg_or_zero" "rZ")))]
2382   ""
2383   "csinc\\t%<w>0, %<w>4, %<w>3, %M1"
2384   [(set_attr "v8type" "csel")
2385    (set_attr "mode" "<MODE>")]
2386 )
2387
2388 (define_insn "*csinv3<mode>_insn"
2389   [(set (match_operand:GPI 0 "register_operand" "=r")
2390         (if_then_else:GPI
2391           (match_operator:GPI 1 "aarch64_comparison_operator"
2392            [(match_operand:CC 2 "cc_register" "") (const_int 0)])
2393           (not:GPI (match_operand:GPI 3 "register_operand" "r"))
2394           (match_operand:GPI 4 "aarch64_reg_or_zero" "rZ")))]
2395   ""
2396   "csinv\\t%<w>0, %<w>4, %<w>3, %M1"
2397   [(set_attr "v8type" "csel")
2398    (set_attr "mode" "<MODE>")])
2399
2400 (define_insn "*csneg3<mode>_insn"
2401   [(set (match_operand:GPI 0 "register_operand" "=r")
2402         (if_then_else:GPI
2403           (match_operator:GPI 1 "aarch64_comparison_operator"
2404            [(match_operand:CC 2 "cc_register" "") (const_int 0)])
2405           (neg:GPI (match_operand:GPI 3 "register_operand" "r"))
2406           (match_operand:GPI 4 "aarch64_reg_or_zero" "rZ")))]
2407   ""
2408   "csneg\\t%<w>0, %<w>4, %<w>3, %M1"
2409   [(set_attr "v8type" "csel")
2410    (set_attr "mode" "<MODE>")])
2411
2412 ;; -------------------------------------------------------------------
2413 ;; Logical operations
2414 ;; -------------------------------------------------------------------
2415
2416 (define_insn "<optab><mode>3"
2417   [(set (match_operand:GPI 0 "register_operand" "=r,rk")
2418         (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r")
2419                      (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>")))]
2420   ""
2421   "<logical>\\t%<w>0, %<w>1, %<w>2"
2422   [(set_attr "v8type" "logic,logic_imm")
2423    (set_attr "mode" "<MODE>")])
2424
2425 ;; zero_extend version of above
2426 (define_insn "*<optab>si3_uxtw"
2427   [(set (match_operand:DI 0 "register_operand" "=r,rk")
2428         (zero_extend:DI
2429          (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
2430                      (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
2431   ""
2432   "<logical>\\t%w0, %w1, %w2"
2433   [(set_attr "v8type" "logic,logic_imm")
2434    (set_attr "mode" "SI")])
2435
2436 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
2437   [(set (match_operand:GPI 0 "register_operand" "=r")
2438         (LOGICAL:GPI (SHIFT:GPI
2439                       (match_operand:GPI 1 "register_operand" "r")
2440                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2441                      (match_operand:GPI 3 "register_operand" "r")))]
2442   ""
2443   "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
2444   [(set_attr "v8type" "logic_shift")
2445    (set_attr "mode" "<MODE>")])
2446
2447 ;; zero_extend version of above
2448 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
2449   [(set (match_operand:DI 0 "register_operand" "=r")
2450         (zero_extend:DI
2451          (LOGICAL:SI (SHIFT:SI
2452                       (match_operand:SI 1 "register_operand" "r")
2453                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2454                      (match_operand:SI 3 "register_operand" "r"))))]
2455   ""
2456   "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
2457   [(set_attr "v8type" "logic_shift")
2458    (set_attr "mode" "SI")])
2459
2460 (define_insn "one_cmpl<mode>2"
2461   [(set (match_operand:GPI 0 "register_operand" "=r")
2462         (not:GPI (match_operand:GPI 1 "register_operand" "r")))]
2463   ""
2464   "mvn\\t%<w>0, %<w>1"
2465   [(set_attr "v8type" "logic")
2466    (set_attr "mode" "<MODE>")])
2467
2468 (define_insn "*one_cmpl_<optab><mode>2"
2469   [(set (match_operand:GPI 0 "register_operand" "=r")
2470         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2471                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2472   ""
2473   "mvn\\t%<w>0, %<w>1, <shift> %2"
2474   [(set_attr "v8type" "logic_shift")
2475    (set_attr "mode" "<MODE>")])
2476
2477 (define_insn "*<LOGICAL:optab>_one_cmpl<mode>3"
2478   [(set (match_operand:GPI 0 "register_operand" "=r")
2479         (LOGICAL:GPI (not:GPI
2480                       (match_operand:GPI 1 "register_operand" "r"))
2481                      (match_operand:GPI 2 "register_operand" "r")))]
2482   ""
2483   "<LOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1"
2484   [(set_attr "v8type" "logic")
2485    (set_attr "mode" "<MODE>")])
2486
2487 (define_insn "*<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
2488   [(set (match_operand:GPI 0 "register_operand" "=r")
2489         (LOGICAL:GPI (not:GPI
2490                       (SHIFT:GPI
2491                        (match_operand:GPI 1 "register_operand" "r")
2492                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2493                      (match_operand:GPI 3 "register_operand" "r")))]
2494   ""
2495   "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
2496   [(set_attr "v8type" "logic_shift")
2497    (set_attr "mode" "<MODE>")])
2498
2499 (define_insn "clz<mode>2"
2500   [(set (match_operand:GPI 0 "register_operand" "=r")
2501         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
2502   ""
2503   "clz\\t%<w>0, %<w>1"
2504   [(set_attr "v8type" "clz")
2505    (set_attr "mode" "<MODE>")])
2506
2507 (define_expand "ffs<mode>2"
2508   [(match_operand:GPI 0 "register_operand")
2509    (match_operand:GPI 1 "register_operand")]
2510   ""
2511   {
2512     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
2513     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
2514
2515     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
2516     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
2517     emit_insn (gen_csinc3<mode>_insn (operands[0], x, ccreg, operands[0], const0_rtx));
2518     DONE;
2519   }
2520 )
2521
2522 (define_insn "clrsb<mode>2"
2523   [(set (match_operand:GPI 0 "register_operand" "=r")
2524         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_CLS))]
2525   ""
2526   "cls\\t%<w>0, %<w>1"
2527   [(set_attr "v8type" "clz")
2528    (set_attr "mode" "<MODE>")])
2529
2530 (define_insn "rbit<mode>2"
2531   [(set (match_operand:GPI 0 "register_operand" "=r")
2532         (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
2533   ""
2534   "rbit\\t%<w>0, %<w>1"
2535   [(set_attr "v8type" "rbit")
2536    (set_attr "mode" "<MODE>")])
2537
2538 (define_expand "ctz<mode>2"
2539   [(match_operand:GPI 0 "register_operand")
2540    (match_operand:GPI 1 "register_operand")]
2541   ""
2542   {
2543     emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
2544     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
2545     DONE;
2546   }
2547 )
2548
2549 (define_insn "*and<mode>3nr_compare0"
2550   [(set (reg:CC_NZ CC_REGNUM)
2551         (compare:CC_NZ
2552          (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
2553                   (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
2554          (const_int 0)))]
2555   ""
2556   "tst\\t%<w>0, %<w>1"
2557   [(set_attr "v8type" "logics")
2558    (set_attr "mode" "<MODE>")])
2559
2560 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
2561   [(set (reg:CC_NZ CC_REGNUM)
2562         (compare:CC_NZ
2563          (and:GPI (SHIFT:GPI
2564                    (match_operand:GPI 0 "register_operand" "r")
2565                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
2566                   (match_operand:GPI 2 "register_operand" "r"))
2567         (const_int 0)))]
2568   ""
2569   "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
2570   [(set_attr "v8type" "logics_shift")
2571    (set_attr "mode" "<MODE>")])
2572
2573 ;; -------------------------------------------------------------------
2574 ;; Shifts
2575 ;; -------------------------------------------------------------------
2576
2577 (define_expand "<optab><mode>3"
2578   [(set (match_operand:GPI 0 "register_operand")
2579         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
2580                     (match_operand:QI 2 "nonmemory_operand")))]
2581   ""
2582   {
2583     if (CONST_INT_P (operands[2]))
2584       {
2585         operands[2] = GEN_INT (INTVAL (operands[2])
2586                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2587
2588         if (operands[2] == const0_rtx)
2589           {
2590             emit_insn (gen_mov<mode> (operands[0], operands[1]));
2591             DONE;
2592           }
2593       }
2594   }
2595 )
2596
2597 (define_expand "ashl<mode>3"
2598   [(set (match_operand:SHORT 0 "register_operand")
2599         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
2600                       (match_operand:QI 2 "nonmemory_operand")))]
2601   ""
2602   {
2603     if (CONST_INT_P (operands[2]))
2604       {
2605         operands[2] = GEN_INT (INTVAL (operands[2])
2606                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2607
2608         if (operands[2] == const0_rtx)
2609           {
2610             emit_insn (gen_mov<mode> (operands[0], operands[1]));
2611             DONE;
2612           }
2613       }
2614   }
2615 )
2616
2617 (define_expand "rotr<mode>3"
2618   [(set (match_operand:GPI 0 "register_operand")
2619         (rotatert:GPI (match_operand:GPI 1 "register_operand")
2620                       (match_operand:QI 2 "nonmemory_operand")))]
2621   ""
2622   {
2623     if (CONST_INT_P (operands[2]))
2624       {
2625         operands[2] = GEN_INT (INTVAL (operands[2])
2626                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2627
2628         if (operands[2] == const0_rtx)
2629           {
2630             emit_insn (gen_mov<mode> (operands[0], operands[1]));
2631             DONE;
2632           }
2633       }
2634   }
2635 )
2636
2637 (define_expand "rotl<mode>3"
2638   [(set (match_operand:GPI 0 "register_operand")
2639         (rotatert:GPI (match_operand:GPI 1 "register_operand")
2640                       (match_operand:QI 2 "nonmemory_operand")))]
2641   ""
2642   {
2643     /* (SZ - cnt) % SZ == -cnt % SZ */
2644     if (CONST_INT_P (operands[2]))
2645       {
2646         operands[2] = GEN_INT ((-INTVAL (operands[2]))
2647                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
2648         if (operands[2] == const0_rtx)
2649           {
2650             emit_insn (gen_mov<mode> (operands[0], operands[1]));
2651             DONE;
2652           }
2653       }
2654     else
2655       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
2656                                         NULL_RTX, 1);
2657   }
2658 )
2659
2660 (define_insn "*<optab><mode>3_insn"
2661   [(set (match_operand:GPI 0 "register_operand" "=r")
2662         (SHIFT:GPI
2663          (match_operand:GPI 1 "register_operand" "r")
2664          (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "rUs<cmode>")))]
2665   ""
2666   "<shift>\\t%<w>0, %<w>1, %<w>2"
2667   [(set_attr "v8type" "shift")
2668    (set_attr "mode" "<MODE>")]
2669 )
2670
2671 ;; zero_extend version of above
2672 (define_insn "*<optab>si3_insn_uxtw"
2673   [(set (match_operand:DI 0 "register_operand" "=r")
2674         (zero_extend:DI (SHIFT:SI
2675          (match_operand:SI 1 "register_operand" "r")
2676          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "rUss"))))]
2677   ""
2678   "<shift>\\t%w0, %w1, %w2"
2679   [(set_attr "v8type" "shift")
2680    (set_attr "mode" "SI")]
2681 )
2682
2683 (define_insn "*ashl<mode>3_insn"
2684   [(set (match_operand:SHORT 0 "register_operand" "=r")
2685         (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
2686                       (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "rUss")))]
2687   ""
2688   "lsl\\t%<w>0, %<w>1, %<w>2"
2689   [(set_attr "v8type" "shift")
2690    (set_attr "mode" "<MODE>")]
2691 )
2692
2693 (define_insn "*<optab><mode>3_insn"
2694   [(set (match_operand:SHORT 0 "register_operand" "=r")
2695         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
2696                       (match_operand 2 "const_int_operand" "n")))]
2697   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
2698 {
2699   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
2700   return "<bfshift>\t%w0, %w1, %2, %3";
2701 }
2702   [(set_attr "v8type" "bfm")
2703    (set_attr "mode" "<MODE>")]
2704 )
2705
2706 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
2707   [(set (match_operand:GPI 0 "register_operand" "=r")
2708         (ANY_EXTEND:GPI
2709          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
2710                        (match_operand 2 "const_int_operand" "n"))))]
2711   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
2712 {
2713   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
2714   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
2715 }
2716   [(set_attr "v8type" "bfm")
2717    (set_attr "mode" "<GPI:MODE>")]
2718 )
2719
2720 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
2721   [(set (match_operand:GPI 0 "register_operand" "=r")
2722         (zero_extend:GPI
2723          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
2724                          (match_operand 2 "const_int_operand" "n"))))]
2725   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
2726 {
2727   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
2728   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
2729 }
2730   [(set_attr "v8type" "bfm")
2731    (set_attr "mode" "<GPI:MODE>")]
2732 )
2733
2734 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
2735   [(set (match_operand:GPI 0 "register_operand" "=r")
2736         (sign_extend:GPI
2737          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
2738                          (match_operand 2 "const_int_operand" "n"))))]
2739   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
2740 {
2741   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
2742   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
2743 }
2744   [(set_attr "v8type" "bfm")
2745    (set_attr "mode" "<GPI:MODE>")]
2746 )
2747
2748 ;; -------------------------------------------------------------------
2749 ;; Bitfields
2750 ;; -------------------------------------------------------------------
2751
2752 (define_expand "<optab>"
2753   [(set (match_operand:DI 0 "register_operand" "=r")
2754         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand" "r")
2755                         (match_operand 2 "const_int_operand" "n")
2756                         (match_operand 3 "const_int_operand" "n")))]
2757   ""
2758   ""
2759 )
2760
2761 (define_insn "*<optab><mode>"
2762   [(set (match_operand:GPI 0 "register_operand" "=r")
2763         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
2764                          (match_operand 2 "const_int_operand" "n")
2765                          (match_operand 3 "const_int_operand" "n")))]
2766   ""
2767   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
2768   [(set_attr "v8type" "bfm")
2769    (set_attr "mode" "<MODE>")]
2770 )
2771
2772 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
2773   [(set (match_operand:GPI 0 "register_operand" "=r")
2774         (ashift:GPI (ANY_EXTEND:GPI
2775                      (match_operand:ALLX 1 "register_operand" "r"))
2776                     (match_operand 2 "const_int_operand" "n")))]
2777   "UINTVAL (operands[2]) < <GPI:sizen>"
2778 {
2779   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
2780               ? GEN_INT (<ALLX:sizen>)
2781               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
2782   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
2783 }
2784   [(set_attr "v8type" "bfm")
2785    (set_attr "mode" "<GPI:MODE>")]
2786 )
2787
2788 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
2789
2790 (define_insn "*andim_ashift<mode>_bfiz"
2791   [(set (match_operand:GPI 0 "register_operand" "=r")
2792         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2793                              (match_operand 2 "const_int_operand" "n"))
2794                  (match_operand 3 "const_int_operand" "n")))]
2795   "exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1) >= 0
2796    && (INTVAL (operands[3]) & ((1 << INTVAL (operands[2])) - 1)) == 0"
2797   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
2798   [(set_attr "v8type" "bfm")
2799    (set_attr "mode" "<MODE>")]
2800 )
2801
2802 (define_insn "bswap<mode>2"
2803   [(set (match_operand:GPI 0 "register_operand" "=r")
2804         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
2805   ""
2806   "rev\\t%<w>0, %<w>1"
2807   [(set_attr "v8type" "rev")
2808    (set_attr "mode" "<MODE>")]
2809 )
2810
2811 (define_insn "bswaphi2"
2812   [(set (match_operand:HI 0 "register_operand" "=r")
2813         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
2814   ""
2815   "rev16\\t%w0, %w1"
2816   [(set_attr "v8type" "rev")
2817    (set_attr "mode" "HI")]
2818 )
2819
2820 ;; zero_extend version of above
2821 (define_insn "*bswapsi2_uxtw"
2822   [(set (match_operand:DI 0 "register_operand" "=r")
2823         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
2824   ""
2825   "rev\\t%w0, %w1"
2826   [(set_attr "v8type" "rev")
2827    (set_attr "mode" "SI")]
2828 )
2829
2830 ;; -------------------------------------------------------------------
2831 ;; Floating-point intrinsics
2832 ;; -------------------------------------------------------------------
2833
2834 ;; frint floating-point round to integral standard patterns.
2835 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round.
2836
2837 (define_insn "<frint_pattern><mode>2"
2838   [(set (match_operand:GPF 0 "register_operand" "=w")
2839         (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2840          FRINT))]
2841   "TARGET_FLOAT"
2842   "frint<frint_suffix>\\t%<s>0, %<s>1"
2843   [(set_attr "v8type" "frint")
2844    (set_attr "mode" "<MODE>")]
2845 )
2846
2847 ;; frcvt floating-point round to integer and convert standard patterns.
2848 ;; Expands to lbtrunc, lceil, lfloor, lround.
2849 (define_insn "l<fcvt_pattern><su_optab><GPF:mode><GPI:mode>2"
2850   [(set (match_operand:GPI 0 "register_operand" "=r")
2851         (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
2852                       FCVT)))]
2853   "TARGET_FLOAT"
2854   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF:s>1"
2855   [(set_attr "v8type" "fcvtf2i")
2856    (set_attr "mode" "<GPF:MODE>")
2857    (set_attr "mode2" "<GPI:MODE>")]
2858 )
2859
2860 ;; fma - no throw
2861
2862 (define_insn "fma<mode>4"
2863   [(set (match_operand:GPF 0 "register_operand" "=w")
2864         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
2865                  (match_operand:GPF 2 "register_operand" "w")
2866                  (match_operand:GPF 3 "register_operand" "w")))]
2867   "TARGET_FLOAT"
2868   "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
2869   [(set_attr "v8type" "fmadd")
2870    (set_attr "mode" "<MODE>")]
2871 )
2872
2873 (define_insn "fnma<mode>4"
2874   [(set (match_operand:GPF 0 "register_operand" "=w")
2875         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
2876                  (match_operand:GPF 2 "register_operand" "w")
2877                  (match_operand:GPF 3 "register_operand" "w")))]
2878   "TARGET_FLOAT"
2879   "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
2880   [(set_attr "v8type" "fmadd")
2881    (set_attr "mode" "<MODE>")]
2882 )
2883
2884 (define_insn "fms<mode>4"
2885   [(set (match_operand:GPF 0 "register_operand" "=w")
2886         (fma:GPF (match_operand:GPF 1 "register_operand" "w")
2887                  (match_operand:GPF 2 "register_operand" "w")
2888                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
2889   "TARGET_FLOAT"
2890   "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3"
2891   [(set_attr "v8type" "fmadd")
2892    (set_attr "mode" "<MODE>")]
2893 )
2894
2895 (define_insn "fnms<mode>4"
2896   [(set (match_operand:GPF 0 "register_operand" "=w")
2897         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
2898                  (match_operand:GPF 2 "register_operand" "w")
2899                  (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))]
2900   "TARGET_FLOAT"
2901   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
2902   [(set_attr "v8type" "fmadd")
2903    (set_attr "mode" "<MODE>")]
2904 )
2905
2906 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
2907 (define_insn "*fnmadd<mode>4"
2908   [(set (match_operand:GPF 0 "register_operand" "=w")
2909         (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w")
2910                           (match_operand:GPF 2 "register_operand" "w")
2911                           (match_operand:GPF 3 "register_operand" "w"))))]
2912   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
2913   "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3"
2914   [(set_attr "v8type" "fmadd")
2915    (set_attr "mode" "<MODE>")]
2916 )
2917
2918 ;; -------------------------------------------------------------------
2919 ;; Floating-point conversions
2920 ;; -------------------------------------------------------------------
2921
2922 (define_insn "extendsfdf2"
2923   [(set (match_operand:DF 0 "register_operand" "=w")
2924         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
2925   "TARGET_FLOAT"
2926   "fcvt\\t%d0, %s1"
2927   [(set_attr "v8type" "fcvt")
2928    (set_attr "mode" "DF")
2929    (set_attr "mode2" "SF")]
2930 )
2931
2932 (define_insn "truncdfsf2"
2933   [(set (match_operand:SF 0 "register_operand" "=w")
2934         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
2935   "TARGET_FLOAT"
2936   "fcvt\\t%s0, %d1"
2937   [(set_attr "v8type" "fcvt")
2938    (set_attr "mode" "SF")
2939    (set_attr "mode2" "DF")]
2940 )
2941
2942 (define_insn "fix_trunc<GPF:mode><GPI:mode>2"
2943   [(set (match_operand:GPI 0 "register_operand" "=r")
2944         (fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
2945   "TARGET_FLOAT"
2946   "fcvtzs\\t%<GPI:w>0, %<GPF:s>1"
2947   [(set_attr "v8type" "fcvtf2i")
2948    (set_attr "mode" "<GPF:MODE>")
2949    (set_attr "mode2" "<GPI:MODE>")]
2950 )
2951
2952 (define_insn "fixuns_trunc<GPF:mode><GPI:mode>2"
2953   [(set (match_operand:GPI 0 "register_operand" "=r")
2954         (unsigned_fix:GPI (match_operand:GPF 1 "register_operand" "w")))]
2955   "TARGET_FLOAT"
2956   "fcvtzu\\t%<GPI:w>0, %<GPF:s>1"
2957   [(set_attr "v8type" "fcvtf2i")
2958    (set_attr "mode" "<GPF:MODE>")
2959    (set_attr "mode2" "<GPI:MODE>")]
2960 )
2961
2962 (define_insn "float<GPI:mode><GPF:mode>2"
2963   [(set (match_operand:GPF 0 "register_operand" "=w")
2964         (float:GPF (match_operand:GPI 1 "register_operand" "r")))]
2965   "TARGET_FLOAT"
2966   "scvtf\\t%<GPF:s>0, %<GPI:w>1"
2967   [(set_attr "v8type" "fcvti2f")
2968    (set_attr "mode" "<GPF:MODE>")
2969    (set_attr "mode2" "<GPI:MODE>")]
2970 )
2971
2972 (define_insn "floatuns<GPI:mode><GPF:mode>2"
2973   [(set (match_operand:GPF 0 "register_operand" "=w")
2974         (unsigned_float:GPF (match_operand:GPI 1 "register_operand" "r")))]
2975   "TARGET_FLOAT"
2976   "ucvtf\\t%<GPF:s>0, %<GPI:w>1"
2977   [(set_attr "v8type" "fcvt")
2978    (set_attr "mode" "<GPF:MODE>")
2979    (set_attr "mode2" "<GPI:MODE>")]
2980 )
2981
2982 ;; -------------------------------------------------------------------
2983 ;; Floating-point arithmetic
2984 ;; -------------------------------------------------------------------
2985
2986 (define_insn "add<mode>3"
2987   [(set (match_operand:GPF 0 "register_operand" "=w")
2988         (plus:GPF
2989          (match_operand:GPF 1 "register_operand" "w")
2990          (match_operand:GPF 2 "register_operand" "w")))]
2991   "TARGET_FLOAT"
2992   "fadd\\t%<s>0, %<s>1, %<s>2"
2993   [(set_attr "v8type" "fadd")
2994    (set_attr "mode" "<MODE>")]
2995 )
2996
2997 (define_insn "sub<mode>3"
2998   [(set (match_operand:GPF 0 "register_operand" "=w")
2999         (minus:GPF
3000          (match_operand:GPF 1 "register_operand" "w")
3001          (match_operand:GPF 2 "register_operand" "w")))]
3002   "TARGET_FLOAT"
3003   "fsub\\t%<s>0, %<s>1, %<s>2"
3004   [(set_attr "v8type" "fadd")
3005    (set_attr "mode" "<MODE>")]
3006 )
3007
3008 (define_insn "mul<mode>3"
3009   [(set (match_operand:GPF 0 "register_operand" "=w")
3010         (mult:GPF
3011          (match_operand:GPF 1 "register_operand" "w")
3012          (match_operand:GPF 2 "register_operand" "w")))]
3013   "TARGET_FLOAT"
3014   "fmul\\t%<s>0, %<s>1, %<s>2"
3015   [(set_attr "v8type" "fmul")
3016    (set_attr "mode" "<MODE>")]
3017 )
3018
3019 (define_insn "*fnmul<mode>3"
3020   [(set (match_operand:GPF 0 "register_operand" "=w")
3021         (mult:GPF
3022                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
3023                  (match_operand:GPF 2 "register_operand" "w")))]
3024   "TARGET_FLOAT"
3025   "fnmul\\t%<s>0, %<s>1, %<s>2"
3026   [(set_attr "v8type" "fmul")
3027    (set_attr "mode" "<MODE>")]
3028 )
3029
3030 (define_insn "div<mode>3"
3031   [(set (match_operand:GPF 0 "register_operand" "=w")
3032         (div:GPF
3033          (match_operand:GPF 1 "register_operand" "w")
3034          (match_operand:GPF 2 "register_operand" "w")))]
3035   "TARGET_FLOAT"
3036   "fdiv\\t%<s>0, %<s>1, %<s>2"
3037   [(set_attr "v8type" "fdiv")
3038    (set_attr "mode" "<MODE>")]
3039 )
3040
3041 (define_insn "neg<mode>2"
3042   [(set (match_operand:GPF 0 "register_operand" "=w")
3043         (neg:GPF (match_operand:GPF 1 "register_operand" "w")))]
3044   "TARGET_FLOAT"
3045   "fneg\\t%<s>0, %<s>1"
3046   [(set_attr "v8type" "ffarith")
3047    (set_attr "mode" "<MODE>")]
3048 )
3049
3050 (define_insn "sqrt<mode>2"
3051   [(set (match_operand:GPF 0 "register_operand" "=w")
3052         (sqrt:GPF (match_operand:GPF 1 "register_operand" "w")))]
3053   "TARGET_FLOAT"
3054   "fsqrt\\t%<s>0, %<s>1"
3055   [(set_attr "v8type" "fsqrt")
3056    (set_attr "mode" "<MODE>")]
3057 )
3058
3059 (define_insn "abs<mode>2"
3060   [(set (match_operand:GPF 0 "register_operand" "=w")
3061         (abs:GPF (match_operand:GPF 1 "register_operand" "w")))]
3062   "TARGET_FLOAT"
3063   "fabs\\t%<s>0, %<s>1"
3064   [(set_attr "v8type" "ffarith")
3065    (set_attr "mode" "<MODE>")]
3066 )
3067
3068 ;; Given that smax/smin do not specify the result when either input is NaN,
3069 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
3070 ;; for smin.
3071
3072 (define_insn "smax<mode>3"
3073   [(set (match_operand:GPF 0 "register_operand" "=w")
3074         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
3075                   (match_operand:GPF 2 "register_operand" "w")))]
3076   "TARGET_FLOAT"
3077   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
3078   [(set_attr "v8type" "fminmax")
3079    (set_attr "mode" "<MODE>")]
3080 )
3081
3082 (define_insn "smin<mode>3"
3083   [(set (match_operand:GPF 0 "register_operand" "=w")
3084         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
3085                   (match_operand:GPF 2 "register_operand" "w")))]
3086   "TARGET_FLOAT"
3087   "fminnm\\t%<s>0, %<s>1, %<s>2"
3088   [(set_attr "v8type" "fminmax")
3089    (set_attr "mode" "<MODE>")]
3090 )
3091
3092 ;; -------------------------------------------------------------------
3093 ;; Reload support
3094 ;; -------------------------------------------------------------------
3095
3096 ;; Reload SP+imm where imm cannot be handled by a single ADD instruction.  
3097 ;; Must load imm into a scratch register and copy SP to the dest reg before
3098 ;; adding, since SP cannot be used as a source register in an ADD
3099 ;; instruction.
3100 (define_expand "reload_sp_immediate"
3101   [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
3102                    (match_operand:DI 1 "" ""))
3103              (clobber (match_operand:TI 2 "register_operand" "=&r"))])]
3104   ""
3105   {
3106     rtx sp = XEXP (operands[1], 0);
3107     rtx val = XEXP (operands[1], 1);
3108     unsigned regno = REGNO (operands[2]);
3109     rtx scratch = operands[1];
3110     gcc_assert (GET_CODE (operands[1]) == PLUS);
3111     gcc_assert (sp == stack_pointer_rtx);
3112     gcc_assert (CONST_INT_P (val));
3113
3114     /* It is possible that one of the registers we got for operands[2]
3115        might coincide with that of operands[0] (which is why we made
3116        it TImode).  Pick the other one to use as our scratch.  */
3117     if (regno == REGNO (operands[0]))
3118       regno++;
3119     scratch = gen_rtx_REG (DImode, regno);
3120
3121     emit_move_insn (scratch, val);
3122     emit_move_insn (operands[0], sp);
3123     emit_insn (gen_adddi3 (operands[0], operands[0], scratch));
3124     DONE;
3125   }
3126 )
3127
3128 (define_expand "aarch64_reload_mov<mode>"
3129   [(set (match_operand:TX 0 "register_operand" "=w")
3130         (match_operand:TX 1 "register_operand" "w"))
3131    (clobber (match_operand:DI 2 "register_operand" "=&r"))
3132   ]
3133   ""
3134   {
3135     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
3136     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
3137     gen_aarch64_movtilow_tilow (op0, op1);
3138     gen_aarch64_movdi_tihigh (operands[2], op1);
3139     gen_aarch64_movtihigh_di (op0, operands[2]);
3140     DONE;
3141   }
3142 )
3143
3144 ;; The following secondary reload helpers patterns are invoked
3145 ;; after or during reload as we don't want these patterns to start
3146 ;; kicking in during the combiner.
3147  
3148 (define_insn "aarch64_movdi_tilow"
3149   [(set (match_operand:DI 0 "register_operand" "=r")
3150         (truncate:DI (match_operand:TI 1 "register_operand" "w")))]
3151   "reload_completed || reload_in_progress"
3152   "fmov\\t%x0, %d1"
3153   [(set_attr "v8type" "fmovf2i")
3154    (set_attr "mode"   "DI")
3155    (set_attr "length" "4")
3156   ])
3157
3158 (define_insn "aarch64_movdi_tihigh"
3159   [(set (match_operand:DI 0 "register_operand" "=r")
3160         (truncate:DI
3161           (lshiftrt:TI (match_operand:TI 1 "register_operand" "w")
3162                        (const_int 64))))]
3163   "reload_completed || reload_in_progress"
3164   "fmov\\t%x0, %1.d[1]"
3165   [(set_attr "v8type" "fmovf2i")
3166    (set_attr "mode"   "DI")
3167    (set_attr "length" "4")
3168   ])
3169
3170 (define_insn "aarch64_movtihigh_di"
3171   [(set (zero_extract:TI (match_operand:TI 0 "register_operand" "+w")
3172                          (const_int 64) (const_int 64))
3173         (zero_extend:TI (match_operand:DI 1 "register_operand" "r")))]
3174   "reload_completed || reload_in_progress"
3175   "fmov\\t%0.d[1], %x1"
3176
3177   [(set_attr "v8type" "fmovi2f")
3178    (set_attr "mode"   "DI")
3179    (set_attr "length" "4")
3180   ])
3181
3182 (define_insn "aarch64_movtilow_di"
3183   [(set (match_operand:TI 0 "register_operand" "=w")
3184         (zero_extend:TI (match_operand:DI 1 "register_operand" "r")))]
3185   "reload_completed || reload_in_progress"
3186   "fmov\\t%d0, %x1"
3187
3188   [(set_attr "v8type" "fmovi2f")
3189    (set_attr "mode"   "DI")
3190    (set_attr "length" "4")
3191   ])
3192
3193 (define_insn "aarch64_movtilow_tilow"
3194   [(set (match_operand:TI 0 "register_operand" "=w")
3195         (zero_extend:TI 
3196           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
3197   "reload_completed || reload_in_progress"
3198   "fmov\\t%d0, %d1"
3199
3200   [(set_attr "v8type" "fmovi2f")
3201    (set_attr "mode"   "DI")
3202    (set_attr "length" "4")
3203   ])
3204
3205 ;; There is a deliberate reason why the parameters of high and lo_sum's
3206 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
3207 ;; and lo_sum's to be used with the labels defining the jump tables in
3208 ;; rodata section.
3209
3210 (define_insn "add_losym"
3211   [(set (match_operand:DI 0 "register_operand" "=r")
3212         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
3213                    (match_operand 2 "aarch64_valid_symref" "S")))]
3214   ""
3215   "add\\t%0, %1, :lo12:%a2"
3216   [(set_attr "v8type" "alu")
3217    (set_attr "mode" "DI")]
3218
3219 )
3220
3221 (define_insn "ldr_got_small"
3222   [(set (match_operand:DI 0 "register_operand" "=r")
3223         (unspec:DI [(mem:DI (lo_sum:DI
3224                               (match_operand:DI 1 "register_operand" "r")
3225                               (match_operand:DI 2 "aarch64_valid_symref" "S")))]
3226                    UNSPEC_GOTSMALLPIC))]
3227   ""
3228   "ldr\\t%0, [%1, #:got_lo12:%a2]"
3229   [(set_attr "v8type" "load1")
3230    (set_attr "mode" "DI")]
3231 )
3232
3233 (define_insn "aarch64_load_tp_hard"
3234   [(set (match_operand:DI 0 "register_operand" "=r")
3235         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
3236   ""
3237   "mrs\\t%0, tpidr_el0"
3238   [(set_attr "v8type" "mrs")
3239    (set_attr "mode" "DI")]
3240 )
3241
3242 ;; The TLS ABI specifically requires that the compiler does not schedule
3243 ;; instructions in the TLS stubs, in order to enable linker relaxation.
3244 ;; Therefore we treat the stubs as an atomic sequence.
3245 (define_expand "tlsgd_small"
3246  [(parallel [(set (match_operand 0 "register_operand" "")
3247                   (call (mem:DI (match_dup 2)) (const_int 1)))
3248              (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
3249              (clobber (reg:DI LR_REGNUM))])]
3250  ""
3251 {
3252   operands[2] = aarch64_tls_get_addr ();
3253 })
3254
3255 (define_insn "*tlsgd_small"
3256   [(set (match_operand 0 "register_operand" "")
3257         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
3258    (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
3259    (clobber (reg:DI LR_REGNUM))
3260   ]
3261   ""
3262   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
3263   [(set_attr "v8type" "call")
3264    (set_attr "length" "16")])
3265
3266 (define_insn "tlsie_small"
3267   [(set (match_operand:DI 0 "register_operand" "=r")
3268         (unspec:DI [(match_operand:DI 1 "aarch64_tls_ie_symref" "S")]
3269                    UNSPEC_GOTSMALLTLS))]
3270   ""
3271   "adrp\\t%0, %A1\;ldr\\t%0, [%0, #%L1]"
3272   [(set_attr "v8type" "load1")
3273    (set_attr "mode" "DI")
3274    (set_attr "length" "8")]
3275 )
3276
3277 (define_insn "tlsle_small"
3278   [(set (match_operand:DI 0 "register_operand" "=r")
3279         (unspec:DI [(match_operand:DI 1 "register_operand" "r")
3280                    (match_operand:DI 2 "aarch64_tls_le_symref" "S")]
3281                    UNSPEC_GOTSMALLTLS))]
3282   ""
3283   "add\\t%0, %1, #%G2\;add\\t%0, %0, #%L2"
3284   [(set_attr "v8type" "alu")
3285    (set_attr "mode" "DI")
3286    (set_attr "length" "8")]
3287 )
3288
3289 (define_insn "tlsdesc_small"
3290   [(set (reg:DI R0_REGNUM)
3291         (unspec:DI [(match_operand:DI 0 "aarch64_valid_symref" "S")]
3292                    UNSPEC_TLSDESC))
3293    (clobber (reg:DI LR_REGNUM))
3294    (clobber (match_scratch:DI 1 "=r"))]
3295   "TARGET_TLS_DESC"
3296   "adrp\\tx0, %A0\;ldr\\t%1, [x0, #%L0]\;add\\tx0, x0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
3297   [(set_attr "v8type" "call")
3298    (set_attr "length" "16")])
3299
3300 (define_insn "stack_tie"
3301   [(set (mem:BLK (scratch))
3302         (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
3303                      (match_operand:DI 1 "register_operand" "rk")]
3304                     UNSPEC_PRLG_STK))]
3305   ""
3306   ""
3307   [(set_attr "length" "0")]
3308 )
3309
3310 ;; Named pattern for expanding thread pointer reference.
3311 (define_expand "get_thread_pointerdi"
3312   [(match_operand:DI 0 "register_operand" "=r")]
3313   ""
3314 {
3315   rtx tmp = aarch64_load_tp (operands[0]);
3316   if (tmp != operands[0])
3317     emit_move_insn (operands[0], tmp);
3318   DONE;
3319 })
3320
3321 ;; AdvSIMD Stuff
3322 (include "aarch64-simd.md")
3323
3324 ;; Atomic Operations
3325 (include "atomics.md")