Fix wrong code by arm_final_prescan with fp16 move instructions
[official-gcc.git] / gcc / config / arm / vfp.md
blob61b6477ad470a7c3db8c251c44d650d1c54f998c
1 ;; ARM VFP instruction patterns
2 ;; Copyright (C) 2003-2017 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery.
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.
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.
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/>.  */
21 ;; Patterns for HI moves which provide more data transfer instructions when VFP
22 ;; support is enabled.
23 (define_insn "*arm_movhi_vfp"
24  [(set
25    (match_operand:HI 0 "nonimmediate_operand"
26     "=rk,  r, r, m, r, *t,  r, *t")
27    (match_operand:HI 1 "general_operand"
28     "rIk, K, n, r, mi, r, *t, *t"))]
29  "TARGET_ARM && TARGET_HARD_FLOAT
30   && !TARGET_VFP_FP16INST
31   && (register_operand (operands[0], HImode)
32        || register_operand (operands[1], HImode))"
34   switch (which_alternative)
35     {
36     case 0:
37       return "mov%?\t%0, %1\t%@ movhi";
38     case 1:
39       return "mvn%?\t%0, #%B1\t%@ movhi";
40     case 2:
41       return "movw%?\t%0, %L1\t%@ movhi";
42     case 3:
43       return "strh%?\t%1, %0\t%@ movhi";
44     case 4:
45       return "ldrh%?\t%0, %1\t%@ movhi";
46     case 5:
47     case 6:
48       return "vmov%?\t%0, %1\t%@ int";
49     case 7:
50       return "vmov%?.f32\t%0, %1\t%@ int";
51     default:
52       gcc_unreachable ();
53     }
55  [(set_attr "predicable" "yes")
56   (set_attr_alternative "type"
57    [(if_then_else
58      (match_operand 1 "const_int_operand" "")
59      (const_string "mov_imm")
60      (const_string "mov_reg"))
61     (const_string "mvn_imm")
62     (const_string "mov_imm")
63     (const_string "store_4")
64     (const_string "load_4")
65     (const_string "f_mcr")
66     (const_string "f_mrc")
67     (const_string "fmov")])
68   (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
69   (set_attr "pool_range" "*, *, *, *, 256, *, *, *")
70   (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *")
71   (set_attr "length" "4")]
74 (define_insn "*thumb2_movhi_vfp"
75  [(set
76    (match_operand:HI 0 "nonimmediate_operand"
77     "=rk, r, l, r, m, r, *t, r, *t")
78    (match_operand:HI 1 "general_operand"
79     "rk, I, Py, n, r, m, r, *t, *t"))]
80  "TARGET_THUMB2 && TARGET_HARD_FLOAT
81   && !TARGET_VFP_FP16INST
82   && (register_operand (operands[0], HImode)
83        || register_operand (operands[1], HImode))"
85   switch (which_alternative)
86     {
87     case 0:
88     case 1:
89     case 2:
90       return "mov%?\t%0, %1\t%@ movhi";
91     case 3:
92       return "movw%?\t%0, %L1\t%@ movhi";
93     case 4:
94       return "strh%?\t%1, %0\t%@ movhi";
95     case 5:
96       return "ldrh%?\t%0, %1\t%@ movhi";
97     case 6:
98     case 7:
99       return "vmov%?\t%0, %1\t%@ int";
100     case 8:
101       return "vmov%?.f32\t%0, %1\t%@ int";
102     default:
103       gcc_unreachable ();
104     }
106  [(set_attr "predicable" "yes")
107   (set_attr "predicable_short_it"
108    "yes, no, yes, no, no, no, no, no, no")
109   (set_attr "type"
110    "mov_reg, mov_imm, mov_imm, mov_imm, store_4, load_4,\
111     f_mcr, f_mrc, fmov")
112   (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *")
113   (set_attr "pool_range" "*, *, *, *, *, 4094, *, *, *")
114   (set_attr "neg_pool_range" "*, *, *, *, *, 250, *, *, *")
115   (set_attr "length" "2, 4, 2, 4, 4, 4, 4, 4, 4")]
118 ;; Patterns for HI moves which provide more data transfer instructions when FP16
119 ;; instructions are available.
120 (define_insn "*arm_movhi_fp16"
121  [(set
122    (match_operand:HI 0 "nonimmediate_operand"
123     "=r,  r, r, m, r, *t,  r, *t")
124    (match_operand:HI 1 "general_operand"
125     "rIk, K, n, r, mi, r, *t, *t"))]
126  "TARGET_ARM && TARGET_VFP_FP16INST
127   && (register_operand (operands[0], HImode)
128        || register_operand (operands[1], HImode))"
130   switch (which_alternative)
131     {
132     case 0:
133       return "mov%?\t%0, %1\t%@ movhi";
134     case 1:
135       return "mvn%?\t%0, #%B1\t%@ movhi";
136     case 2:
137       return "movw%?\t%0, %L1\t%@ movhi";
138     case 3:
139       return "strh%?\t%1, %0\t%@ movhi";
140     case 4:
141       return "ldrh%?\t%0, %1\t%@ movhi";
142     case 5:
143     case 6:
144       return "vmov.f16\t%0, %1\t%@ int";
145     case 7:
146       return "vmov%?.f32\t%0, %1\t%@ int";
147     default:
148       gcc_unreachable ();
149     }
151  [(set_attr "predicable" "yes, yes, yes, yes, yes, no, no, yes")
152   (set_attr_alternative "type"
153    [(if_then_else
154      (match_operand 1 "const_int_operand" "")
155      (const_string "mov_imm")
156      (const_string "mov_reg"))
157     (const_string "mvn_imm")
158     (const_string "mov_imm")
159     (const_string "store_4")
160     (const_string "load_4")
161     (const_string "f_mcr")
162     (const_string "f_mrc")
163     (const_string "fmov")])
164   (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
165   (set_attr "pool_range" "*, *, *, *, 256, *, *, *")
166   (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *")
167   (set_attr "length" "4")]
170 (define_insn "*thumb2_movhi_fp16"
171  [(set
172    (match_operand:HI 0 "nonimmediate_operand"
173     "=rk, r, l, r, m, r, *t, r, *t")
174    (match_operand:HI 1 "general_operand"
175     "rk, I, Py, n, r, m, r, *t, *t"))]
176  "TARGET_THUMB2 && TARGET_VFP_FP16INST
177   && (register_operand (operands[0], HImode)
178        || register_operand (operands[1], HImode))"
180   switch (which_alternative)
181     {
182     case 0:
183     case 1:
184     case 2:
185       return "mov%?\t%0, %1\t%@ movhi";
186     case 3:
187       return "movw%?\t%0, %L1\t%@ movhi";
188     case 4:
189       return "strh%?\t%1, %0\t%@ movhi";
190     case 5:
191       return "ldrh%?\t%0, %1\t%@ movhi";
192     case 6:
193     case 7:
194       return "vmov.f16\t%0, %1\t%@ int";
195     case 8:
196       return "vmov%?.f32\t%0, %1\t%@ int";
197     default:
198       gcc_unreachable ();
199     }
201  [(set_attr "predicable"
202    "yes, yes, yes, yes, yes, yes, no, no, yes")
203   (set_attr "predicable_short_it"
204    "yes, no, yes, no, no, no, no, no, no")
205   (set_attr "type"
206    "mov_reg, mov_imm, mov_imm, mov_imm, store_4, load_4,\
207     f_mcr, f_mrc, fmov")
208   (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *")
209   (set_attr "pool_range" "*, *, *, *, *, 4094, *, *, *")
210   (set_attr "neg_pool_range" "*, *, *, *, *, 250, *, *, *")
211   (set_attr "length" "2, 4, 2, 4, 4, 4, 4, 4, 4")]
214 ;; SImode moves
215 ;; ??? For now do not allow loading constants into vfp regs.  This causes
216 ;; problems because small constants get converted into adds.
217 (define_insn "*arm_movsi_vfp"
218   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv")
219       (match_operand:SI 1 "general_operand"        "rk, I,K,j,mi,rk,r,*t,*t,*Uvi,*t"))]
220   "TARGET_ARM && TARGET_HARD_FLOAT
221    && (   s_register_operand (operands[0], SImode)
222        || s_register_operand (operands[1], SImode))"
223   "*
224   switch (which_alternative)
225     {
226     case 0: case 1:
227       return \"mov%?\\t%0, %1\";
228     case 2:
229       return \"mvn%?\\t%0, #%B1\";
230     case 3:
231       return \"movw%?\\t%0, %1\";
232     case 4:
233       return \"ldr%?\\t%0, %1\";
234     case 5:
235       return \"str%?\\t%1, %0\";
236     case 6:
237       return \"vmov%?\\t%0, %1\\t%@ int\";
238     case 7:
239       return \"vmov%?\\t%0, %1\\t%@ int\";
240     case 8:
241       return \"vmov%?.f32\\t%0, %1\\t%@ int\";
242     case 9: case 10:
243       return output_move_vfp (operands);
244     default:
245       gcc_unreachable ();
246     }
247   "
248   [(set_attr "predicable" "yes")
249    (set_attr "type" "mov_reg,mov_reg,mvn_imm,mov_imm,load_4,store_4,
250                      f_mcr,f_mrc,fmov,f_loads,f_stores")
251    (set_attr "pool_range"     "*,*,*,*,4096,*,*,*,*,1020,*")
252    (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")]
255 ;; See thumb2.md:thumb2_movsi_insn for an explanation of the split
256 ;; high/low register alternatives for loads and stores here.
257 ;; The l/Py alternative should come after r/I to ensure that the short variant
258 ;; is chosen with length 2 when the instruction is predicated for
259 ;; arm_restrict_it.
260 (define_insn "*thumb2_movsi_vfp"
261   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r, l,*hk,m, *m,*t, r,*t,*t,  *Uv")
262         (match_operand:SI 1 "general_operand"      "rk,I,Py,K,j,mi,*mi,l,*hk, r,*t,*t,*Uvi,*t"))]
263   "TARGET_THUMB2 && TARGET_HARD_FLOAT
264    && (   s_register_operand (operands[0], SImode)
265        || s_register_operand (operands[1], SImode))"
266   "*
267   switch (which_alternative)
268     {
269     case 0:
270     case 1:
271     case 2:
272       return \"mov%?\\t%0, %1\";
273     case 3:
274       return \"mvn%?\\t%0, #%B1\";
275     case 4:
276       return \"movw%?\\t%0, %1\";
277     case 5:
278     case 6:
279       return \"ldr%?\\t%0, %1\";
280     case 7:
281     case 8:
282       return \"str%?\\t%1, %0\";
283     case 9:
284       return \"vmov%?\\t%0, %1\\t%@ int\";
285     case 10:
286       return \"vmov%?\\t%0, %1\\t%@ int\";
287     case 11:
288       return \"vmov%?.f32\\t%0, %1\\t%@ int\";
289     case 12: case 13:
290       return output_move_vfp (operands);
291     default:
292       gcc_unreachable ();
293     }
294   "
295   [(set_attr "predicable" "yes")
296    (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no")
297    (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_imm,load_4,load_4,store_4,store_4,f_mcr,f_mrc,fmov,f_loads,f_stores")
298    (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4")
299    (set_attr "pool_range"     "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*")
300    (set_attr "neg_pool_range" "*,*,*,*,*,   0,   0,*,*,*,*,*,1008,*")]
304 ;; DImode moves
306 (define_insn "*movdi_vfp"
307   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,q,q,m,w,!r,w,w, Uv")
308        (match_operand:DI 1 "di_operand"              "r,rDa,Db,Dc,mi,mi,q,r,w,w,Uvi,w"))]
309   "TARGET_32BIT && TARGET_HARD_FLOAT
310    && (   register_operand (operands[0], DImode)
311        || register_operand (operands[1], DImode))
312    && !(TARGET_NEON && CONST_INT_P (operands[1])
313         && neon_immediate_valid_for_move (operands[1], DImode, NULL, NULL))"
314   "*
315   switch (which_alternative)
316     {
317     case 0: 
318     case 1:
319     case 2:
320     case 3:
321       return \"#\";
322     case 4:
323     case 5:
324     case 6:
325       return output_move_double (operands, true, NULL);
326     case 7:
327       return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\";
328     case 8:
329       return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\";
330     case 9:
331       if (TARGET_VFP_SINGLE)
332         return \"vmov%?.f32\\t%0, %1\\t%@ int\;vmov%?.f32\\t%p0, %p1\\t%@ int\";
333       else
334         return \"vmov%?.f64\\t%P0, %P1\\t%@ int\";
335     case 10: case 11:
336       return output_move_vfp (operands);
337     default:
338       gcc_unreachable ();
339     }
340   "
341   [(set_attr "type" "multiple,multiple,multiple,multiple,load_8,load_8,store_8,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored")
342    (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8)
343                               (eq_attr "alternative" "2") (const_int 12)
344                               (eq_attr "alternative" "3") (const_int 16)
345                               (eq_attr "alternative" "4,5,6")
346                                (symbol_ref "arm_count_output_move_double_insns (operands) * 4")
347                               (eq_attr "alternative" "9")
348                                (if_then_else
349                                  (match_test "TARGET_VFP_SINGLE")
350                                  (const_int 8)
351                                  (const_int 4))]
352                               (const_int 4)))
353    (set_attr "predicable"    "yes")
354    (set_attr "arm_pool_range"     "*,*,*,*,1020,4096,*,*,*,*,1020,*")
355    (set_attr "thumb2_pool_range"     "*,*,*,*,1018,4094,*,*,*,*,1018,*")
356    (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
357    (set (attr "ce_count") (symbol_ref "get_attr_length (insn) / 4"))
358    (set_attr "arch"           "t2,any,any,any,a,t2,any,any,any,any,any,any")]
361 ;; HFmode moves
363 (define_insn "*movhf_vfp_fp16"
364   [(set (match_operand:HF 0 "nonimmediate_operand"
365                           "= r,m,t,r,t,r,t,t,Um,r")
366         (match_operand:HF 1 "general_operand"
367                           "  m,r,t,r,r,t,Dv,Um,t,F"))]
368   "TARGET_32BIT
369    && TARGET_VFP_FP16INST
370    && (s_register_operand (operands[0], HFmode)
371        || s_register_operand (operands[1], HFmode))"
373   switch (which_alternative)
374     {
375     case 0: /* ARM register from memory.  */
376       return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
377     case 1: /* Memory from ARM register.  */
378       return \"strh%?\\t%1, %0\\t%@ __fp16\";
379     case 2: /* S register from S register.  */
380       return \"vmov\\t%0, %1\t%@ __fp16\";
381     case 3: /* ARM register from ARM register.  */
382       return \"mov%?\\t%0, %1\\t%@ __fp16\";
383     case 4: /* S register from ARM register.  */
384     case 5: /* ARM register from S register.  */
385     case 6: /* S register from immediate.  */
386       return \"vmov.f16\\t%0, %1\t%@ __fp16\";
387     case 7: /* S register from memory.  */
388       return \"vld1.16\\t{%z0}, %A1\";
389     case 8: /* Memory from S register.  */
390       return \"vst1.16\\t{%z1}, %A0\";
391     case 9: /* ARM register from constant.  */
392       {
393         long bits;
394         rtx ops[4];
396         bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
397                                HFmode);
398         ops[0] = operands[0];
399         ops[1] = GEN_INT (bits);
400         ops[2] = GEN_INT (bits & 0xff00);
401         ops[3] = GEN_INT (bits & 0x00ff);
403         if (arm_arch_thumb2)
404           output_asm_insn (\"movw\\t%0, %1\", ops);
405         else
406           output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
407         return \"\";
408        }
409     default:
410       gcc_unreachable ();
411     }
413   [(set_attr "conds" "*, *, unconditional, *, unconditional, unconditional,\
414                       unconditional, unconditional, unconditional,\
415                       unconditional")
416    (set_attr "predicable" "yes, yes, no, yes, no, no, no, no, no, no")
417    (set_attr "predicable_short_it" "no, no, no, yes,\
418                                     no, no, no, no,\
419                                     no, no")
420    (set_attr_alternative "type"
421     [(const_string "load_4") (const_string "store_4")
422      (const_string "fmov") (const_string "mov_reg")
423      (const_string "f_mcr") (const_string "f_mrc")
424      (const_string "fconsts") (const_string "neon_load1_1reg")
425      (const_string "neon_store1_1reg")
426      (if_then_else (match_test "arm_arch_thumb2")
427       (const_string "mov_imm")
428       (const_string "multiple"))])
429    (set_attr_alternative "length"
430     [(const_int 4) (const_int 4)
431      (const_int 4) (const_int 4)
432      (const_int 4) (const_int 4)
433      (const_int 4) (const_int 4)
434      (const_int 4)
435      (if_then_else (match_test "arm_arch_thumb2")
436       (const_int 4)
437       (const_int 8))])]
440 (define_insn "*movhf_vfp_neon"
441   [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r")
442         (match_operand:HF 1 "general_operand"      " Um, t,m,r,t,r,r,t,F"))]
443   "TARGET_32BIT
444    && TARGET_HARD_FLOAT && TARGET_NEON_FP16
445    && !TARGET_VFP_FP16INST
446    && (   s_register_operand (operands[0], HFmode)
447        || s_register_operand (operands[1], HFmode))"
448   "*
449   switch (which_alternative)
450     {
451     case 0:     /* S register from memory */
452       return \"vld1.16\\t{%z0}, %A1\";
453     case 1:     /* memory from S register */
454       return \"vst1.16\\t{%z1}, %A0\";
455     case 2:     /* ARM register from memory */
456       return \"ldrh\\t%0, %1\\t%@ __fp16\";
457     case 3:     /* memory from ARM register */
458       return \"strh\\t%1, %0\\t%@ __fp16\";
459     case 4:     /* S register from S register */
460       return \"vmov.f32\\t%0, %1\";
461     case 5:     /* ARM register from ARM register */
462       return \"mov\\t%0, %1\\t%@ __fp16\";
463     case 6:     /* S register from ARM register */
464       return \"vmov\\t%0, %1\";
465     case 7:     /* ARM register from S register */
466       return \"vmov\\t%0, %1\";
467     case 8:     /* ARM register from constant */
468       {
469         long bits;
470         rtx ops[4];
472         bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
473                                HFmode);
474         ops[0] = operands[0];
475         ops[1] = GEN_INT (bits);
476         ops[2] = GEN_INT (bits & 0xff00);
477         ops[3] = GEN_INT (bits & 0x00ff);
479         if (arm_arch_thumb2)
480           output_asm_insn (\"movw\\t%0, %1\", ops);
481         else
482           output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
483         return \"\";
484        }
485     default:
486       gcc_unreachable ();
487     }
488   "
489   [(set_attr "conds" "unconditional")
490    (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\
491                      load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
492    (set_attr "length" "4,4,4,4,4,4,4,4,8")]
495 ;; FP16 without element load/store instructions.
496 (define_insn "*movhf_vfp"
497   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
498         (match_operand:HF 1 "general_operand"      " m,r,t,r,r,t,F"))]
499   "TARGET_32BIT
500    && TARGET_HARD_FLOAT
501    && !TARGET_NEON_FP16
502    && !TARGET_VFP_FP16INST
503    && (   s_register_operand (operands[0], HFmode)
504        || s_register_operand (operands[1], HFmode))"
505   "*
506   switch (which_alternative)
507     {
508     case 0:     /* ARM register from memory */
509       return \"ldrh\\t%0, %1\\t%@ __fp16\";
510     case 1:     /* memory from ARM register */
511       return \"strh\\t%1, %0\\t%@ __fp16\";
512     case 2:     /* S register from S register */
513       return \"vmov.f32\\t%0, %1\";
514     case 3:     /* ARM register from ARM register */
515       return \"mov\\t%0, %1\\t%@ __fp16\";
516     case 4:     /* S register from ARM register */
517       return \"vmov\\t%0, %1\";
518     case 5:     /* ARM register from S register */
519       return \"vmov\\t%0, %1\";
520     case 6:     /* ARM register from constant */
521       {
522         long bits;
523         rtx ops[4];
525         bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
526                                HFmode);
527         ops[0] = operands[0];
528         ops[1] = GEN_INT (bits);
529         ops[2] = GEN_INT (bits & 0xff00);
530         ops[3] = GEN_INT (bits & 0x00ff);
532         if (arm_arch_thumb2)
533           output_asm_insn (\"movw\\t%0, %1\", ops);
534         else
535           output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
536         return \"\";
537        }
538     default:
539       gcc_unreachable ();
540     }
541   "
542   [(set_attr "conds" "unconditional")
543    (set_attr "type" "load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
544    (set_attr "length" "4,4,4,4,4,4,8")]
548 ;; SFmode moves
549 ;; Disparage the w<->r cases because reloading an invalid address is
550 ;; preferable to loading the value via integer registers.
552 (define_insn "*movsf_vfp"
553   [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t  ,Uv,r ,m,t,r")
554         (match_operand:SF 1 "general_operand"      " ?r,t,Dv,UvE,t, mE,r,t,r"))]
555   "TARGET_ARM && TARGET_HARD_FLOAT
556    && (   s_register_operand (operands[0], SFmode)
557        || s_register_operand (operands[1], SFmode))"
558   "*
559   switch (which_alternative)
560     {
561     case 0:
562       return \"vmov%?\\t%0, %1\";
563     case 1:
564       return \"vmov%?\\t%0, %1\";
565     case 2:
566       return \"vmov%?.f32\\t%0, %1\";
567     case 3: case 4:
568       return output_move_vfp (operands);
569     case 5:
570       return \"ldr%?\\t%0, %1\\t%@ float\";
571     case 6:
572       return \"str%?\\t%1, %0\\t%@ float\";
573     case 7:
574       return \"vmov%?.f32\\t%0, %1\";
575     case 8:
576       return \"mov%?\\t%0, %1\\t%@ float\";
577     default:
578       gcc_unreachable ();
579     }
580   "
581   [(set_attr "predicable" "yes")
582    (set_attr "type"
583      "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
584    (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
585    (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
588 (define_insn "*thumb2_movsf_vfp"
589   [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t  ,Uv,r ,m,t,r")
590         (match_operand:SF 1 "general_operand"      " ?r,t,Dv,UvE,t, mE,r,t,r"))]
591   "TARGET_THUMB2 && TARGET_HARD_FLOAT
592    && (   s_register_operand (operands[0], SFmode)
593        || s_register_operand (operands[1], SFmode))"
594   "*
595   switch (which_alternative)
596     {
597     case 0:
598       return \"vmov%?\\t%0, %1\";
599     case 1:
600       return \"vmov%?\\t%0, %1\";
601     case 2:
602       return \"vmov%?.f32\\t%0, %1\";
603     case 3: case 4:
604       return output_move_vfp (operands);
605     case 5:
606       return \"ldr%?\\t%0, %1\\t%@ float\";
607     case 6:
608       return \"str%?\\t%1, %0\\t%@ float\";
609     case 7:
610       return \"vmov%?.f32\\t%0, %1\";
611     case 8:
612       return \"mov%?\\t%0, %1\\t%@ float\";
613     default:
614       gcc_unreachable ();
615     }
616   "
617   [(set_attr "predicable" "yes")
618    (set_attr "type"
619      "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
620    (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*")
621    (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
624 ;; DFmode moves
626 (define_insn "*movdf_vfp"
627   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w  ,Uv,r, m,w,r")
628         (match_operand:DF 1 "soft_df_operand"              " ?r,w,Dy,G,UvF,w ,mF,r,w,r"))]
629   "TARGET_ARM && TARGET_HARD_FLOAT
630    && (   register_operand (operands[0], DFmode)
631        || register_operand (operands[1], DFmode))"
632   "*
633   {
634     switch (which_alternative)
635       {
636       case 0:
637         return \"vmov%?\\t%P0, %Q1, %R1\";
638       case 1:
639         return \"vmov%?\\t%Q0, %R0, %P1\";
640       case 2:
641         gcc_assert (TARGET_VFP_DOUBLE);
642         return \"vmov%?.f64\\t%P0, %1\";
643       case 3:
644         gcc_assert (TARGET_VFP_DOUBLE);
645         return \"vmov.i64\\t%P0, #0\\t%@ float\";
646       case 4: case 5:
647         return output_move_vfp (operands);
648       case 6: case 7:
649         return output_move_double (operands, true, NULL);
650       case 8:
651         if (TARGET_VFP_SINGLE)
652           return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
653         else
654           return \"vmov%?.f64\\t%P0, %P1\";
655       case 9:
656         return \"#\";
657       default:
658         gcc_unreachable ();
659       }
660     }
661   "
662   [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,f_stored,\
663                      load_8,store_8,ffarithd,multiple")
664    (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
665                                (eq_attr "alternative" "8")
666                                 (if_then_else
667                                  (match_test "TARGET_VFP_SINGLE")
668                                  (const_int 8)
669                                  (const_int 4))]
670                               (const_int 4)))
671    (set_attr "predicable" "yes,yes,yes,no,yes,yes,yes,yes,yes,yes")
672    (set_attr "pool_range" "*,*,*,*,1020,*,1020,*,*,*")
673    (set_attr "neg_pool_range" "*,*,*,*,1004,*,1004,*,*,*")
674    (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
677 (define_insn "*thumb2_movdf_vfp"
678   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w  ,Uv,r ,m,w,r")
679         (match_operand:DF 1 "soft_df_operand"              " ?r,w,Dy,G,UvF,w, mF,r, w,r"))]
680   "TARGET_THUMB2 && TARGET_HARD_FLOAT
681    && (   register_operand (operands[0], DFmode)
682        || register_operand (operands[1], DFmode))"
683   "*
684   {
685     switch (which_alternative)
686       {
687       case 0:
688         return \"vmov%?\\t%P0, %Q1, %R1\";
689       case 1:
690         return \"vmov%?\\t%Q0, %R0, %P1\";
691       case 2:
692         gcc_assert (TARGET_VFP_DOUBLE);
693         return \"vmov%?.f64\\t%P0, %1\";
694       case 3:
695         gcc_assert (TARGET_VFP_DOUBLE);
696         return \"vmov.i64\\t%P0, #0\\t%@ float\";
697       case 4: case 5:
698         return output_move_vfp (operands);
699       case 6: case 7: case 9:
700         return output_move_double (operands, true, NULL);
701       case 8:
702         if (TARGET_VFP_SINGLE)
703           return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
704         else
705           return \"vmov%?.f64\\t%P0, %P1\";
706       default:
707         abort ();
708       }
709     }
710   "
711   [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,\
712                      f_stored,load_8,store_8,ffarithd,multiple")
713    (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
714                                (eq_attr "alternative" "8")
715                                 (if_then_else
716                                  (match_test "TARGET_VFP_SINGLE")
717                                  (const_int 8)
718                                  (const_int 4))]
719                               (const_int 4)))
720    (set_attr "pool_range" "*,*,*,*,1018,*,4094,*,*,*")
721    (set_attr "neg_pool_range" "*,*,*,*,1008,*,0,*,*,*")
722    (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
726 ;; Conditional move patterns
728 (define_insn "*movsfcc_vfp"
729   [(set (match_operand:SF   0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
730         (if_then_else:SF
731           (match_operator   3 "arm_comparison_operator"
732             [(match_operand 4 "cc_register" "") (const_int 0)])
733           (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
734           (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
735   "TARGET_ARM && TARGET_HARD_FLOAT"
736   "@
737    vmov%D3.f32\\t%0, %2
738    vmov%d3.f32\\t%0, %1
739    vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
740    vmov%D3\\t%0, %2
741    vmov%d3\\t%0, %1
742    vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
743    vmov%D3\\t%0, %2
744    vmov%d3\\t%0, %1
745    vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
746    [(set_attr "conds" "use")
747     (set_attr "length" "4,4,8,4,4,8,4,4,8")
748     (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
751 (define_insn "*thumb2_movsfcc_vfp"
752   [(set (match_operand:SF   0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
753         (if_then_else:SF
754           (match_operator   3 "arm_comparison_operator"
755             [(match_operand 4 "cc_register" "") (const_int 0)])
756           (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
757           (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
758   "TARGET_THUMB2 && TARGET_HARD_FLOAT && !arm_restrict_it"
759   "@
760    it\\t%D3\;vmov%D3.f32\\t%0, %2
761    it\\t%d3\;vmov%d3.f32\\t%0, %1
762    ite\\t%D3\;vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
763    it\\t%D3\;vmov%D3\\t%0, %2
764    it\\t%d3\;vmov%d3\\t%0, %1
765    ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
766    it\\t%D3\;vmov%D3\\t%0, %2
767    it\\t%d3\;vmov%d3\\t%0, %1
768    ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
769    [(set_attr "conds" "use")
770     (set_attr "length" "6,6,10,6,6,10,6,6,10")
771     (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
774 (define_insn "*movdfcc_vfp"
775   [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
776         (if_then_else:DF
777           (match_operator   3 "arm_comparison_operator"
778             [(match_operand 4 "cc_register" "") (const_int 0)])
779           (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
780           (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
781   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
782   "@
783    vmov%D3.f64\\t%P0, %P2
784    vmov%d3.f64\\t%P0, %P1
785    vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
786    vmov%D3\\t%P0, %Q2, %R2
787    vmov%d3\\t%P0, %Q1, %R1
788    vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
789    vmov%D3\\t%Q0, %R0, %P2
790    vmov%d3\\t%Q0, %R0, %P1
791    vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
792    [(set_attr "conds" "use")
793     (set_attr "length" "4,4,8,4,4,8,4,4,8")
794     (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcr,f_mrrc,f_mrrc,f_mrrc")]
797 (define_insn "*thumb2_movdfcc_vfp"
798   [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
799         (if_then_else:DF
800           (match_operator   3 "arm_comparison_operator"
801             [(match_operand 4 "cc_register" "") (const_int 0)])
802           (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
803           (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
804   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && !arm_restrict_it"
805   "@
806    it\\t%D3\;vmov%D3.f64\\t%P0, %P2
807    it\\t%d3\;vmov%d3.f64\\t%P0, %P1
808    ite\\t%D3\;vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
809    it\t%D3\;vmov%D3\\t%P0, %Q2, %R2
810    it\t%d3\;vmov%d3\\t%P0, %Q1, %R1
811    ite\\t%D3\;vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
812    it\t%D3\;vmov%D3\\t%Q0, %R0, %P2
813    it\t%d3\;vmov%d3\\t%Q0, %R0, %P1
814    ite\\t%D3\;vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
815    [(set_attr "conds" "use")
816     (set_attr "length" "6,6,10,6,6,10,6,6,10")
817     (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcrr,f_mrrc,f_mrrc,f_mrrc")]
821 ;; Sign manipulation functions
823 (define_insn "*abssf2_vfp"
824   [(set (match_operand:SF         0 "s_register_operand" "=t")
825         (abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
826   "TARGET_32BIT && TARGET_HARD_FLOAT"
827   "vabs%?.f32\\t%0, %1"
828   [(set_attr "predicable" "yes")
829    (set_attr "type" "ffariths")]
832 (define_insn "*absdf2_vfp"
833   [(set (match_operand:DF         0 "s_register_operand" "=w")
834         (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
835   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
836   "vabs%?.f64\\t%P0, %P1"
837   [(set_attr "predicable" "yes")
838    (set_attr "type" "ffarithd")]
841 (define_insn "*negsf2_vfp"
842   [(set (match_operand:SF         0 "s_register_operand" "=t,?r")
843         (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))]
844   "TARGET_32BIT && TARGET_HARD_FLOAT"
845   "@
846    vneg%?.f32\\t%0, %1
847    eor%?\\t%0, %1, #-2147483648"
848   [(set_attr "predicable" "yes")
849    (set_attr "type" "ffariths")]
852 (define_insn_and_split "*negdf2_vfp"
853   [(set (match_operand:DF         0 "s_register_operand" "=w,?r,?r")
854         (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
855   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
856   "@
857    vneg%?.f64\\t%P0, %P1
858    #
859    #"
860   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
861    && arm_general_register_operand (operands[0], DFmode)"
862   [(set (match_dup 0) (match_dup 1))]
863   "
864   if (REGNO (operands[0]) == REGNO (operands[1]))
865     {
866       operands[0] = gen_highpart (SImode, operands[0]);
867       operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
868     }
869   else
870     {
871       rtx in_hi, in_lo, out_hi, out_lo;
873       in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
874                            GEN_INT (0x80000000));
875       in_lo = gen_lowpart (SImode, operands[1]);
876       out_hi = gen_highpart (SImode, operands[0]);
877       out_lo = gen_lowpart (SImode, operands[0]);
879       if (REGNO (in_lo) == REGNO (out_hi))
880         {
881           emit_insn (gen_rtx_SET (out_lo, in_lo));
882           operands[0] = out_hi;
883           operands[1] = in_hi;
884         }
885       else
886         {
887           emit_insn (gen_rtx_SET (out_hi, in_hi));
888           operands[0] = out_lo;
889           operands[1] = in_lo;
890         }
891     }
892   "
893   [(set_attr "predicable" "yes")
894    (set_attr "length" "4,4,8")
895    (set_attr "type" "ffarithd")]
898 ;; ABS and NEG for FP16.
899 (define_insn "<absneg_str>hf2"
900   [(set (match_operand:HF 0 "s_register_operand" "=w")
901     (ABSNEG:HF (match_operand:HF 1 "s_register_operand" "w")))]
902  "TARGET_VFP_FP16INST"
903  "v<absneg_str>.f16\t%0, %1"
904   [(set_attr "conds" "unconditional")
905    (set_attr "type" "ffariths")]
908 (define_expand "neon_vabshf"
909  [(set
910    (match_operand:HF 0 "s_register_operand")
911    (abs:HF (match_operand:HF 1 "s_register_operand")))]
912  "TARGET_VFP_FP16INST"
914   emit_insn (gen_abshf2 (operands[0], operands[1]));
915   DONE;
918 ;; VRND for FP16.
919 (define_insn "neon_v<fp16_rnd_str>hf"
920   [(set (match_operand:HF 0 "s_register_operand" "=w")
921     (unspec:HF
922      [(match_operand:HF 1 "s_register_operand" "w")]
923      FP16_RND))]
924  "TARGET_VFP_FP16INST"
925  "<fp16_rnd_insn>.f16\t%0, %1"
926  [(set_attr "conds" "unconditional")
927   (set_attr "type" "neon_fp_round_s")]
930 (define_insn "neon_vrndihf"
931   [(set (match_operand:HF 0 "s_register_operand" "=w")
932     (unspec:HF
933      [(match_operand:HF 1 "s_register_operand" "w")]
934      UNSPEC_VRNDI))]
935   "TARGET_VFP_FP16INST"
936   "vrintr.f16\t%0, %1"
937  [(set_attr "conds" "unconditional")
938   (set_attr "type" "neon_fp_round_s")]
941 ;; Arithmetic insns
943 (define_insn "addhf3"
944   [(set
945     (match_operand:HF 0 "s_register_operand" "=w")
946     (plus:HF
947      (match_operand:HF 1 "s_register_operand" "w")
948      (match_operand:HF 2 "s_register_operand" "w")))]
949  "TARGET_VFP_FP16INST"
950  "vadd.f16\t%0, %1, %2"
951   [(set_attr "conds" "unconditional")
952    (set_attr "type" "fadds")]
955 (define_insn "*addsf3_vfp"
956   [(set (match_operand:SF          0 "s_register_operand" "=t")
957         (plus:SF (match_operand:SF 1 "s_register_operand" "t")
958                  (match_operand:SF 2 "s_register_operand" "t")))]
959   "TARGET_32BIT && TARGET_HARD_FLOAT"
960   "vadd%?.f32\\t%0, %1, %2"
961   [(set_attr "predicable" "yes")
962    (set_attr "type" "fadds")]
965 (define_insn "*adddf3_vfp"
966   [(set (match_operand:DF          0 "s_register_operand" "=w")
967         (plus:DF (match_operand:DF 1 "s_register_operand" "w")
968                  (match_operand:DF 2 "s_register_operand" "w")))]
969   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
970   "vadd%?.f64\\t%P0, %P1, %P2"
971   [(set_attr "predicable" "yes")
972    (set_attr "type" "faddd")]
975 (define_insn "subhf3"
976  [(set
977    (match_operand:HF 0 "s_register_operand" "=w")
978    (minus:HF
979     (match_operand:HF 1 "s_register_operand" "w")
980     (match_operand:HF 2 "s_register_operand" "w")))]
981  "TARGET_VFP_FP16INST"
982  "vsub.f16\t%0, %1, %2"
983   [(set_attr "conds" "unconditional")
984    (set_attr "type" "fadds")]
987 (define_insn "*subsf3_vfp"
988   [(set (match_operand:SF           0 "s_register_operand" "=t")
989         (minus:SF (match_operand:SF 1 "s_register_operand" "t")
990                   (match_operand:SF 2 "s_register_operand" "t")))]
991   "TARGET_32BIT && TARGET_HARD_FLOAT"
992   "vsub%?.f32\\t%0, %1, %2"
993   [(set_attr "predicable" "yes")
994    (set_attr "type" "fadds")]
997 (define_insn "*subdf3_vfp"
998   [(set (match_operand:DF           0 "s_register_operand" "=w")
999         (minus:DF (match_operand:DF 1 "s_register_operand" "w")
1000                   (match_operand:DF 2 "s_register_operand" "w")))]
1001   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1002   "vsub%?.f64\\t%P0, %P1, %P2"
1003   [(set_attr "predicable" "yes")
1004    (set_attr "type" "faddd")]
1008 ;; Division insns
1010 ;; FP16 Division.
1011 (define_insn "divhf3"
1012   [(set
1013     (match_operand:HF      0 "s_register_operand" "=w")
1014     (div:HF
1015      (match_operand:HF 1 "s_register_operand" "w")
1016      (match_operand:HF 2 "s_register_operand" "w")))]
1017   "TARGET_VFP_FP16INST"
1018   "vdiv.f16\t%0, %1, %2"
1019   [(set_attr "conds" "unconditional")
1020    (set_attr "type" "fdivs")]
1023 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1024 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1025 ; earlier.
1026 (define_insn "*divsf3_vfp"
1027   [(set (match_operand:SF         0 "s_register_operand" "=&t,t")
1028         (div:SF (match_operand:SF 1 "s_register_operand" "t,t")
1029                 (match_operand:SF 2 "s_register_operand" "t,t")))]
1030   "TARGET_32BIT && TARGET_HARD_FLOAT"
1031   "vdiv%?.f32\\t%0, %1, %2"
1032   [(set_attr "predicable" "yes")
1033    (set_attr "arch" "*,armv6_or_vfpv3")
1034    (set_attr "type" "fdivs")]
1037 (define_insn "*divdf3_vfp"
1038   [(set (match_operand:DF         0 "s_register_operand" "=&w,w")
1039         (div:DF (match_operand:DF 1 "s_register_operand" "w,w")
1040                 (match_operand:DF 2 "s_register_operand" "w,w")))]
1041   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1042   "vdiv%?.f64\\t%P0, %P1, %P2"
1043   [(set_attr "predicable" "yes")
1044    (set_attr "arch" "*,armv6_or_vfpv3")
1045    (set_attr "type" "fdivd")]
1049 ;; Multiplication insns
1051 (define_insn "mulhf3"
1052  [(set
1053    (match_operand:HF 0 "s_register_operand" "=w")
1054    (mult:HF (match_operand:HF 1 "s_register_operand" "w")
1055             (match_operand:HF 2 "s_register_operand" "w")))]
1056   "TARGET_VFP_FP16INST"
1057   "vmul.f16\t%0, %1, %2"
1058   [(set_attr "conds" "unconditional")
1059    (set_attr "type" "fmuls")]
1062 (define_insn "*mulsf3_vfp"
1063   [(set (match_operand:SF          0 "s_register_operand" "=t")
1064         (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1065                  (match_operand:SF 2 "s_register_operand" "t")))]
1066   "TARGET_32BIT && TARGET_HARD_FLOAT"
1067   "vmul%?.f32\\t%0, %1, %2"
1068   [(set_attr "predicable" "yes")
1069    (set_attr "type" "fmuls")]
1072 (define_insn "*muldf3_vfp"
1073   [(set (match_operand:DF          0 "s_register_operand" "=w")
1074         (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1075                  (match_operand:DF 2 "s_register_operand" "w")))]
1076   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1077   "vmul%?.f64\\t%P0, %P1, %P2"
1078   [(set_attr "predicable" "yes")
1079    (set_attr "type" "fmuld")]
1082 (define_insn "*mulsf3neghf_vfp"
1083   [(set (match_operand:HF                  0 "s_register_operand" "=t")
1084         (mult:HF (neg:HF (match_operand:HF 1 "s_register_operand" "t"))
1085                  (match_operand:HF         2 "s_register_operand" "t")))]
1086   "TARGET_VFP_FP16INST && !flag_rounding_math"
1087   "vnmul.f16\\t%0, %1, %2"
1088   [(set_attr "conds" "unconditional")
1089    (set_attr "type" "fmuls")]
1092 (define_insn "*negmulhf3_vfp"
1093   [(set (match_operand:HF                  0 "s_register_operand" "=t")
1094         (neg:HF (mult:HF (match_operand:HF 1 "s_register_operand" "t")
1095                  (match_operand:HF         2 "s_register_operand" "t"))))]
1096   "TARGET_VFP_FP16INST"
1097   "vnmul.f16\\t%0, %1, %2"
1098   [(set_attr "conds" "unconditional")
1099    (set_attr "type" "fmuls")]
1102 (define_insn "*mulsf3negsf_vfp"
1103   [(set (match_operand:SF                  0 "s_register_operand" "=t")
1104         (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
1105                  (match_operand:SF         2 "s_register_operand" "t")))]
1106   "TARGET_32BIT && TARGET_HARD_FLOAT && !flag_rounding_math"
1107   "vnmul%?.f32\\t%0, %1, %2"
1108   [(set_attr "predicable" "yes")
1109    (set_attr "type" "fmuls")]
1112 (define_insn "*negmulsf3_vfp"
1113   [(set (match_operand:SF                  0 "s_register_operand" "=t")
1114         (neg:SF (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1115                  (match_operand:SF         2 "s_register_operand" "t"))))]
1116   "TARGET_32BIT && TARGET_HARD_FLOAT"
1117   "vnmul%?.f32\\t%0, %1, %2"
1118   [(set_attr "predicable" "yes")
1119    (set_attr "type" "fmuls")]
1122 (define_insn "*muldf3negdf_vfp"
1123   [(set (match_operand:DF                  0 "s_register_operand" "=w")
1124         (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
1125                  (match_operand:DF         2 "s_register_operand" "w")))]
1126   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
1127   && !flag_rounding_math"
1128   "vnmul%?.f64\\t%P0, %P1, %P2"
1129   [(set_attr "predicable" "yes")
1130    (set_attr "type" "fmuld")]
1133 (define_insn "*negmuldf3_vfp"
1134   [(set (match_operand:DF                  0 "s_register_operand" "=w")
1135         (neg:DF (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1136                  (match_operand:DF         2 "s_register_operand" "w"))))]
1137   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1138   "vnmul%?.f64\\t%P0, %P1, %P2"
1139   [(set_attr "predicable" "yes")
1140    (set_attr "type" "fmuld")]
1144 ;; Multiply-accumulate insns
1146 ;; 0 = 1 * 2 + 0
1147 (define_insn "*mulsf3addhf_vfp"
1148  [(set (match_operand:HF 0 "s_register_operand" "=t")
1149        (plus:HF
1150         (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1151                  (match_operand:HF 3 "s_register_operand" "t"))
1152         (match_operand:HF 1 "s_register_operand" "0")))]
1153   "TARGET_VFP_FP16INST"
1154   "vmla.f16\\t%0, %2, %3"
1155   [(set_attr "conds" "unconditional")
1156    (set_attr "type" "fmacs")]
1159 (define_insn "*mulsf3addsf_vfp"
1160   [(set (match_operand:SF                   0 "s_register_operand" "=t")
1161         (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1162                           (match_operand:SF 3 "s_register_operand" "t"))
1163                  (match_operand:SF          1 "s_register_operand" "0")))]
1164   "TARGET_32BIT && TARGET_HARD_FLOAT"
1165   "vmla%?.f32\\t%0, %2, %3"
1166   [(set_attr "predicable" "yes")
1167    (set_attr "type" "fmacs")]
1170 (define_insn "*muldf3adddf_vfp"
1171   [(set (match_operand:DF                   0 "s_register_operand" "=w")
1172         (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1173                           (match_operand:DF 3 "s_register_operand" "w"))
1174                  (match_operand:DF          1 "s_register_operand" "0")))]
1175   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1176   "vmla%?.f64\\t%P0, %P2, %P3"
1177   [(set_attr "predicable" "yes")
1178    (set_attr "type" "fmacd")]
1181 ;; 0 = 1 * 2 - 0
1182 (define_insn "*mulhf3subhf_vfp"
1183   [(set (match_operand:HF 0 "s_register_operand" "=t")
1184         (minus:HF (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1185                            (match_operand:HF 3 "s_register_operand" "t"))
1186                   (match_operand:HF 1 "s_register_operand" "0")))]
1187   "TARGET_VFP_FP16INST"
1188   "vnmls.f16\\t%0, %2, %3"
1189   [(set_attr "conds" "unconditional")
1190    (set_attr "type" "fmacs")]
1193 (define_insn "*mulsf3subsf_vfp"
1194   [(set (match_operand:SF                    0 "s_register_operand" "=t")
1195         (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1196                            (match_operand:SF 3 "s_register_operand" "t"))
1197                   (match_operand:SF          1 "s_register_operand" "0")))]
1198   "TARGET_32BIT && TARGET_HARD_FLOAT"
1199   "vnmls%?.f32\\t%0, %2, %3"
1200   [(set_attr "predicable" "yes")
1201    (set_attr "type" "fmacs")]
1204 (define_insn "*muldf3subdf_vfp"
1205   [(set (match_operand:DF                    0 "s_register_operand" "=w")
1206         (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1207                            (match_operand:DF 3 "s_register_operand" "w"))
1208                   (match_operand:DF          1 "s_register_operand" "0")))]
1209   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1210   "vnmls%?.f64\\t%P0, %P2, %P3"
1211   [(set_attr "predicable" "yes")
1212    (set_attr "type" "fmacd")]
1215 ;; 0 = -(1 * 2) + 0
1216 (define_insn "*mulhf3neghfaddhf_vfp"
1217   [(set (match_operand:HF 0 "s_register_operand" "=t")
1218         (minus:HF (match_operand:HF 1 "s_register_operand" "0")
1219                   (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1220                            (match_operand:HF 3 "s_register_operand" "t"))))]
1221   "TARGET_VFP_FP16INST"
1222   "vmls.f16\\t%0, %2, %3"
1223   [(set_attr "conds" "unconditional")
1224    (set_attr "type" "fmacs")]
1227 (define_insn "*mulsf3negsfaddsf_vfp"
1228   [(set (match_operand:SF                    0 "s_register_operand" "=t")
1229         (minus:SF (match_operand:SF          1 "s_register_operand" "0")
1230                   (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1231                            (match_operand:SF 3 "s_register_operand" "t"))))]
1232   "TARGET_32BIT && TARGET_HARD_FLOAT"
1233   "vmls%?.f32\\t%0, %2, %3"
1234   [(set_attr "predicable" "yes")
1235    (set_attr "type" "fmacs")]
1238 (define_insn "*fmuldf3negdfadddf_vfp"
1239   [(set (match_operand:DF                    0 "s_register_operand" "=w")
1240         (minus:DF (match_operand:DF          1 "s_register_operand" "0")
1241                   (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1242                            (match_operand:DF 3 "s_register_operand" "w"))))]
1243   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1244   "vmls%?.f64\\t%P0, %P2, %P3"
1245   [(set_attr "predicable" "yes")
1246    (set_attr "type" "fmacd")]
1250 ;; 0 = -(1 * 2) - 0
1251 (define_insn "*mulhf3neghfsubhf_vfp"
1252   [(set (match_operand:HF 0 "s_register_operand" "=t")
1253         (minus:HF (mult:HF
1254                    (neg:HF (match_operand:HF 2 "s_register_operand" "t"))
1255                    (match_operand:HF 3 "s_register_operand" "t"))
1256                   (match_operand:HF 1 "s_register_operand" "0")))]
1257   "TARGET_VFP_FP16INST"
1258   "vnmla.f16\\t%0, %2, %3"
1259   [(set_attr "conds" "unconditional")
1260    (set_attr "type" "fmacs")]
1263 (define_insn "*mulsf3negsfsubsf_vfp"
1264   [(set (match_operand:SF                     0 "s_register_operand" "=t")
1265         (minus:SF (mult:SF
1266                     (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
1267                     (match_operand:SF         3 "s_register_operand" "t"))
1268                   (match_operand:SF           1 "s_register_operand" "0")))]
1269   "TARGET_32BIT && TARGET_HARD_FLOAT"
1270   "vnmla%?.f32\\t%0, %2, %3"
1271   [(set_attr "predicable" "yes")
1272    (set_attr "type" "fmacs")]
1275 (define_insn "*muldf3negdfsubdf_vfp"
1276   [(set (match_operand:DF                     0 "s_register_operand" "=w")
1277         (minus:DF (mult:DF
1278                     (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
1279                     (match_operand:DF         3 "s_register_operand" "w"))
1280                   (match_operand:DF           1 "s_register_operand" "0")))]
1281   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1282   "vnmla%?.f64\\t%P0, %P2, %P3"
1283   [(set_attr "predicable" "yes")
1284    (set_attr "type" "fmacd")]
1287 ;; Fused-multiply-accumulate
1289 (define_insn "fmahf4"
1290   [(set (match_operand:HF 0 "register_operand" "=w")
1291     (fma:HF
1292      (match_operand:HF 1 "register_operand" "w")
1293      (match_operand:HF 2 "register_operand" "w")
1294      (match_operand:HF 3 "register_operand" "0")))]
1295  "TARGET_VFP_FP16INST"
1296  "vfma.f16\\t%0, %1, %2"
1297  [(set_attr "conds" "unconditional")
1298   (set_attr "type" "ffmas")]
1301 (define_expand "neon_vfmahf"
1302   [(match_operand:HF 0 "s_register_operand")
1303    (match_operand:HF 1 "s_register_operand")
1304    (match_operand:HF 2 "s_register_operand")
1305    (match_operand:HF 3 "s_register_operand")]
1306   "TARGET_VFP_FP16INST"
1308   emit_insn (gen_fmahf4 (operands[0], operands[2], operands[3],
1309                          operands[1]));
1310   DONE;
1313 (define_insn "fma<SDF:mode>4"
1314   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1315         (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1316                  (match_operand:SDF 2 "register_operand" "<F_constraint>")
1317                  (match_operand:SDF 3 "register_operand" "0")))]
1318   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1319   "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1320   [(set_attr "predicable" "yes")
1321    (set_attr "type" "ffma<vfp_type>")]
1324 (define_insn "fmsubhf4_fp16"
1325  [(set (match_operand:HF 0 "register_operand" "=w")
1326    (fma:HF
1327     (neg:HF (match_operand:HF 1 "register_operand" "w"))
1328     (match_operand:HF 2 "register_operand" "w")
1329     (match_operand:HF 3 "register_operand" "0")))]
1330  "TARGET_VFP_FP16INST"
1331  "vfms.f16\\t%0, %1, %2"
1332  [(set_attr "conds" "unconditional")
1333   (set_attr "type" "ffmas")]
1336 (define_expand "neon_vfmshf"
1337   [(match_operand:HF 0 "s_register_operand")
1338    (match_operand:HF 1 "s_register_operand")
1339    (match_operand:HF 2 "s_register_operand")
1340    (match_operand:HF 3 "s_register_operand")]
1341   "TARGET_VFP_FP16INST"
1343   emit_insn (gen_fmsubhf4_fp16 (operands[0], operands[2], operands[3],
1344                                 operands[1]));
1345   DONE;
1348 (define_insn "*fmsub<SDF:mode>4"
1349   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1350         (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1351                                              "<F_constraint>"))
1352                  (match_operand:SDF 2 "register_operand" "<F_constraint>")
1353                  (match_operand:SDF 3 "register_operand" "0")))]
1354   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1355   "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1356   [(set_attr "predicable" "yes")
1357    (set_attr "type" "ffma<vfp_type>")]
1360 (define_insn "*fnmsubhf4"
1361   [(set (match_operand:HF 0 "register_operand" "=w")
1362         (fma:HF (match_operand:HF 1 "register_operand" "w")
1363                  (match_operand:HF 2 "register_operand" "w")
1364                  (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1365   "TARGET_VFP_FP16INST"
1366   "vfnms.f16\\t%0, %1, %2"
1367   [(set_attr "conds" "unconditional")
1368    (set_attr "type" "ffmas")]
1371 (define_insn "*fnmsub<SDF:mode>4"
1372   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1373         (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1374                  (match_operand:SDF 2 "register_operand" "<F_constraint>")
1375                  (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1376   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1377   "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1378   [(set_attr "predicable" "yes")
1379    (set_attr "type" "ffma<vfp_type>")]
1382 (define_insn "*fnmaddhf4"
1383   [(set (match_operand:HF 0 "register_operand" "=w")
1384         (fma:HF (neg:HF (match_operand:HF 1 "register_operand" "w"))
1385                  (match_operand:HF 2 "register_operand" "w")
1386                  (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1387   "TARGET_VFP_FP16INST"
1388   "vfnma.f16\\t%0, %1, %2"
1389   [(set_attr "conds" "unconditional")
1390    (set_attr "type" "ffmas")]
1393 (define_insn "*fnmadd<SDF:mode>4"
1394   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1395         (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1396                                                "<F_constraint>"))
1397                  (match_operand:SDF 2 "register_operand" "<F_constraint>")
1398                  (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1399   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1400   "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1401   [(set_attr "predicable" "yes")
1402    (set_attr "type" "ffma<vfp_type>")]
1406 ;; Conversion routines
1408 (define_insn "*extendsfdf2_vfp"
1409   [(set (match_operand:DF                  0 "s_register_operand" "=w")
1410         (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
1411   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1412   "vcvt%?.f64.f32\\t%P0, %1"
1413   [(set_attr "predicable" "yes")
1414    (set_attr "type" "f_cvt")]
1417 (define_insn "*truncdfsf2_vfp"
1418   [(set (match_operand:SF                  0 "s_register_operand" "=t")
1419         (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
1420   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1421   "vcvt%?.f32.f64\\t%0, %P1"
1422   [(set_attr "predicable" "yes")
1423    (set_attr "type" "f_cvt")]
1426 (define_insn "extendhfsf2"
1427   [(set (match_operand:SF                  0 "s_register_operand" "=t")
1428         (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))]
1429   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1430   "vcvtb%?.f32.f16\\t%0, %1"
1431   [(set_attr "predicable" "yes")
1432    (set_attr "type" "f_cvt")]
1435 (define_insn "*truncdfhf2"
1436   [(set (match_operand:HF                  0 "s_register_operand" "=t")
1437         (float_truncate:HF (match_operand:DF 1 "s_register_operand" "w")))]
1438   "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1439   "vcvtb%?.f16.f64\\t%0, %P1"
1440   [(set_attr "predicable" "yes")
1441    (set_attr "type" "f_cvt")]
1444 (define_insn "*extendhfdf2"
1445   [(set (match_operand:DF                  0 "s_register_operand" "=w")
1446         (float_extend:DF (match_operand:HF 1 "s_register_operand" "t")))]
1447   "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1448   "vcvtb%?.f64.f16\\t%P0, %1"
1449   [(set_attr "predicable" "yes")
1450    (set_attr "type" "f_cvt")]
1453 (define_insn "truncsfhf2"
1454   [(set (match_operand:HF                  0 "s_register_operand" "=t")
1455         (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
1456   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1457   "vcvtb%?.f16.f32\\t%0, %1"
1458   [(set_attr "predicable" "yes")
1459    (set_attr "type" "f_cvt")]
1462 (define_insn "*truncsisf2_vfp"
1463   [(set (match_operand:SI                 0 "s_register_operand" "=t")
1464         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1465   "TARGET_32BIT && TARGET_HARD_FLOAT"
1466   "vcvt%?.s32.f32\\t%0, %1"
1467   [(set_attr "predicable" "yes")
1468    (set_attr "type" "f_cvtf2i")]
1471 (define_insn "*truncsidf2_vfp"
1472   [(set (match_operand:SI                 0 "s_register_operand" "=t")
1473         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
1474   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1475   "vcvt%?.s32.f64\\t%0, %P1"
1476   [(set_attr "predicable" "yes")
1477    (set_attr "type" "f_cvtf2i")]
1481 (define_insn "fixuns_truncsfsi2"
1482   [(set (match_operand:SI                 0 "s_register_operand" "=t")
1483         (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1484   "TARGET_32BIT && TARGET_HARD_FLOAT"
1485   "vcvt%?.u32.f32\\t%0, %1"
1486   [(set_attr "predicable" "yes")
1487    (set_attr "type" "f_cvtf2i")]
1490 (define_insn "fixuns_truncdfsi2"
1491   [(set (match_operand:SI                 0 "s_register_operand" "=t")
1492         (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
1493   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1494   "vcvt%?.u32.f64\\t%0, %P1"
1495   [(set_attr "predicable" "yes")
1496    (set_attr "type" "f_cvtf2i")]
1500 (define_insn "*floatsisf2_vfp"
1501   [(set (match_operand:SF           0 "s_register_operand" "=t")
1502         (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1503   "TARGET_32BIT && TARGET_HARD_FLOAT"
1504   "vcvt%?.f32.s32\\t%0, %1"
1505   [(set_attr "predicable" "yes")
1506    (set_attr "type" "f_cvti2f")]
1509 (define_insn "*floatsidf2_vfp"
1510   [(set (match_operand:DF           0 "s_register_operand" "=w")
1511         (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1512   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1513   "vcvt%?.f64.s32\\t%P0, %1"
1514   [(set_attr "predicable" "yes")
1515    (set_attr "type" "f_cvti2f")]
1519 (define_insn "floatunssisf2"
1520   [(set (match_operand:SF           0 "s_register_operand" "=t")
1521         (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1522   "TARGET_32BIT && TARGET_HARD_FLOAT"
1523   "vcvt%?.f32.u32\\t%0, %1"
1524   [(set_attr "predicable" "yes")
1525    (set_attr "type" "f_cvti2f")]
1528 (define_insn "floatunssidf2"
1529   [(set (match_operand:DF           0 "s_register_operand" "=w")
1530         (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1531   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1532   "vcvt%?.f64.u32\\t%P0, %1"
1533   [(set_attr "predicable" "yes")
1534    (set_attr "type" "f_cvti2f")]
1538 ;; Sqrt insns.
1540 (define_insn "neon_vsqrthf"
1541   [(set (match_operand:HF 0 "s_register_operand" "=w")
1542         (sqrt:HF (match_operand:HF 1 "s_register_operand" "w")))]
1543   "TARGET_VFP_FP16INST"
1544   "vsqrt.f16\t%0, %1"
1545   [(set_attr "conds" "unconditional")
1546    (set_attr "type" "fsqrts")]
1549 (define_insn "neon_vrsqrtshf"
1550   [(set
1551     (match_operand:HF 0 "s_register_operand" "=w")
1552     (unspec:HF [(match_operand:HF 1 "s_register_operand" "w")
1553                 (match_operand:HF 2 "s_register_operand" "w")]
1554      UNSPEC_VRSQRTS))]
1555  "TARGET_VFP_FP16INST"
1556  "vrsqrts.f16\t%0, %1, %2"
1557  [(set_attr "conds" "unconditional")
1558   (set_attr "type" "fsqrts")]
1561 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1562 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1563 ; earlier.
1564 (define_insn "*sqrtsf2_vfp"
1565   [(set (match_operand:SF          0 "s_register_operand" "=&t,t")
1566         (sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))]
1567   "TARGET_32BIT && TARGET_HARD_FLOAT"
1568   "vsqrt%?.f32\\t%0, %1"
1569   [(set_attr "predicable" "yes")
1570    (set_attr "arch" "*,armv6_or_vfpv3")
1571    (set_attr "type" "fsqrts")]
1574 (define_insn "*sqrtdf2_vfp"
1575   [(set (match_operand:DF          0 "s_register_operand" "=&w,w")
1576         (sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))]
1577   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1578   "vsqrt%?.f64\\t%P0, %P1"
1579   [(set_attr "predicable" "yes")
1580    (set_attr "arch" "*,armv6_or_vfpv3")
1581    (set_attr "type" "fsqrtd")]
1585 ;; Patterns to split/copy vfp condition flags.
1587 (define_insn "*movcc_vfp"
1588   [(set (reg CC_REGNUM)
1589         (reg VFPCC_REGNUM))]
1590   "TARGET_32BIT && TARGET_HARD_FLOAT"
1591   "vmrs%?\\tAPSR_nzcv, FPSCR"
1592   [(set_attr "conds" "set")
1593    (set_attr "type" "f_flag")]
1596 (define_insn_and_split "*cmpsf_split_vfp"
1597   [(set (reg:CCFP CC_REGNUM)
1598         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "t")
1599                       (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1600   "TARGET_32BIT && TARGET_HARD_FLOAT"
1601   "#"
1602   "TARGET_32BIT && TARGET_HARD_FLOAT"
1603   [(set (reg:CCFP VFPCC_REGNUM)
1604         (compare:CCFP (match_dup 0)
1605                       (match_dup 1)))
1606    (set (reg:CCFP CC_REGNUM)
1607         (reg:CCFP VFPCC_REGNUM))]
1608   ""
1611 (define_insn_and_split "*cmpsf_trap_split_vfp"
1612   [(set (reg:CCFPE CC_REGNUM)
1613         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "t")
1614                        (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1615   "TARGET_32BIT && TARGET_HARD_FLOAT"
1616   "#"
1617   "TARGET_32BIT && TARGET_HARD_FLOAT"
1618   [(set (reg:CCFPE VFPCC_REGNUM)
1619         (compare:CCFPE (match_dup 0)
1620                        (match_dup 1)))
1621    (set (reg:CCFPE CC_REGNUM)
1622         (reg:CCFPE VFPCC_REGNUM))]
1623   ""
1626 (define_insn_and_split "*cmpdf_split_vfp"
1627   [(set (reg:CCFP CC_REGNUM)
1628         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w")
1629                       (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1630   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1631   "#"
1632   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1633   [(set (reg:CCFP VFPCC_REGNUM)
1634         (compare:CCFP (match_dup 0)
1635                        (match_dup 1)))
1636    (set (reg:CCFP CC_REGNUM)
1637         (reg:CCFP VFPCC_REGNUM))]
1638   ""
1641 (define_insn_and_split "*cmpdf_trap_split_vfp"
1642   [(set (reg:CCFPE CC_REGNUM)
1643         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w")
1644                        (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1645   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1646   "#"
1647   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1648   [(set (reg:CCFPE VFPCC_REGNUM)
1649         (compare:CCFPE (match_dup 0)
1650                        (match_dup 1)))
1651    (set (reg:CCFPE CC_REGNUM)
1652         (reg:CCFPE VFPCC_REGNUM))]
1653   ""
1657 ;; Comparison patterns
1659 ;; In the compare with FP zero case the ARM Architecture Reference Manual
1660 ;; specifies the immediate to be #0.0.  However, some buggy assemblers only
1661 ;; accept #0.  We don't want to autodetect broken assemblers, so output #0.
1662 (define_insn "*cmpsf_vfp"
1663   [(set (reg:CCFP VFPCC_REGNUM)
1664         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "t,t")
1665                       (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1666   "TARGET_32BIT && TARGET_HARD_FLOAT"
1667   "@
1668    vcmp%?.f32\\t%0, %1
1669    vcmp%?.f32\\t%0, #0"
1670   [(set_attr "predicable" "yes")
1671    (set_attr "type" "fcmps")]
1674 (define_insn "*cmpsf_trap_vfp"
1675   [(set (reg:CCFPE VFPCC_REGNUM)
1676         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "t,t")
1677                        (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1678   "TARGET_32BIT && TARGET_HARD_FLOAT"
1679   "@
1680    vcmpe%?.f32\\t%0, %1
1681    vcmpe%?.f32\\t%0, #0"
1682   [(set_attr "predicable" "yes")
1683    (set_attr "type" "fcmps")]
1686 (define_insn "*cmpdf_vfp"
1687   [(set (reg:CCFP VFPCC_REGNUM)
1688         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w,w")
1689                       (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1690   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1691   "@
1692    vcmp%?.f64\\t%P0, %P1
1693    vcmp%?.f64\\t%P0, #0"
1694   [(set_attr "predicable" "yes")
1695    (set_attr "type" "fcmpd")]
1698 (define_insn "*cmpdf_trap_vfp"
1699   [(set (reg:CCFPE VFPCC_REGNUM)
1700         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w,w")
1701                        (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1702   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1703   "@
1704    vcmpe%?.f64\\t%P0, %P1
1705    vcmpe%?.f64\\t%P0, #0"
1706   [(set_attr "predicable" "yes")
1707    (set_attr "type" "fcmpd")]
1710 ;; Fixed point to floating point conversions.
1711 (define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1712   [(set (match_operand:SF 0 "s_register_operand" "=t")
1713         (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
1714                  (match_operand 2
1715                         "const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1716   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1717   "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2"
1718   [(set_attr "predicable" "yes")
1719    (set_attr "type" "f_cvti2f")]
1722 ;; Not the ideal way of implementing this. Ideally we would be able to split
1723 ;; this into a move to a DP register and then a vcvt.f64.i32
1724 (define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1725   [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1726         (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
1727                  (match_operand 2
1728                      "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
1729   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
1730   && !TARGET_VFP_SINGLE"
1731   "@
1732   vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1733   vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1734   vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1735   [(set_attr "predicable" "yes")
1736    (set_attr "ce_count" "2")
1737    (set_attr "type" "f_cvti2f")
1738    (set_attr "length" "8")]
1741 (define_insn "*combine_vcvtf2i"
1742   [(set (match_operand:SI 0 "s_register_operand" "=t")
1743         (fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0")
1744                                  (match_operand 2
1745                                  "const_double_vcvt_power_of_two" "Dp")))))]
1746   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1747   "vcvt%?.s32.f32\\t%0, %1, %v2"
1748   [(set_attr "predicable" "yes")
1749    (set_attr "type" "f_cvtf2i")]
1752 ;; FP16 conversions.
1753 (define_insn "neon_vcvth<sup>hf"
1754  [(set (match_operand:HF 0 "s_register_operand" "=w")
1755    (unspec:HF
1756     [(match_operand:SI 1 "s_register_operand" "w")]
1757     VCVTH_US))]
1758  "TARGET_VFP_FP16INST"
1759  "vcvt.f16.<sup>%#32\t%0, %1"
1760  [(set_attr "conds" "unconditional")
1761   (set_attr "type" "f_cvti2f")]
1764 (define_insn "neon_vcvth<sup>si"
1765  [(set (match_operand:SI 0 "s_register_operand" "=w")
1766    (unspec:SI
1767     [(match_operand:HF 1 "s_register_operand" "w")]
1768     VCVTH_US))]
1769  "TARGET_VFP_FP16INST"
1770  "vcvt.<sup>%#32.f16\t%0, %1"
1771  [(set_attr "conds" "unconditional")
1772   (set_attr "type" "f_cvtf2i")]
1775 ;; The neon_vcvth<sup>_nhf patterns are used to generate the instruction for the
1776 ;; vcvth_n_f16_<sup>32 arm_fp16 intrinsics.  They are complicated by the
1777 ;; hardware requirement that the source and destination registers are the same
1778 ;; despite having different machine modes.  The approach is to use a temporary
1779 ;; register for the conversion and move that to the correct destination.
1781 ;; Generate an unspec pattern for the intrinsic.
1782 (define_insn "neon_vcvth<sup>_nhf_unspec"
1783  [(set
1784    (match_operand:SI 0 "s_register_operand" "=w")
1785    (unspec:SI
1786     [(match_operand:SI 1 "s_register_operand" "0")
1787      (match_operand:SI 2 "immediate_operand" "i")]
1788     VCVT_HF_US_N))
1789  (set
1790   (match_operand:HF 3 "s_register_operand" "=w")
1791   (float_truncate:HF (float:SF (match_dup 0))))]
1792  "TARGET_VFP_FP16INST"
1794   arm_const_bounds (operands[2], 1, 33);
1795   return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1797   [(set_attr "conds" "unconditional")
1798    (set_attr "type" "f_cvti2f")]
1801 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1802 (define_expand "neon_vcvth<sup>_nhf"
1803  [(match_operand:HF 0 "s_register_operand")
1804   (unspec:HF [(match_operand:SI 1 "s_register_operand")
1805               (match_operand:SI 2 "immediate_operand")]
1806    VCVT_HF_US_N)]
1807 "TARGET_VFP_FP16INST"
1809   rtx op1 = gen_reg_rtx (SImode);
1811   arm_const_bounds (operands[2], 1, 33);
1813   emit_move_insn (op1, operands[1]);
1814   emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2],
1815                                              operands[0]));
1816   DONE;
1819 ;; The neon_vcvth<sup>_nsi patterns are used to generate the instruction for the
1820 ;; vcvth_n_<sup>32_f16 arm_fp16 intrinsics.  They have the same restrictions and
1821 ;; are implemented in the same way as the neon_vcvth<sup>_nhf patterns.
1823 ;; Generate an unspec pattern, constraining the registers.
1824 (define_insn "neon_vcvth<sup>_nsi_unspec"
1825  [(set (match_operand:SI 0 "s_register_operand" "=w")
1826    (unspec:SI
1827     [(fix:SI
1828       (fix:SF
1829        (float_extend:SF
1830         (match_operand:HF 1 "s_register_operand" "w"))))
1831      (match_operand:SI 2 "immediate_operand" "i")]
1832     VCVT_SI_US_N))]
1833  "TARGET_VFP_FP16INST"
1835   arm_const_bounds (operands[2], 1, 33);
1836   return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1838   [(set_attr "conds" "unconditional")
1839    (set_attr "type" "f_cvtf2i")]
1842 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1843 (define_expand "neon_vcvth<sup>_nsi"
1844  [(match_operand:SI 0 "s_register_operand")
1845   (unspec:SI
1846    [(match_operand:HF 1 "s_register_operand")
1847     (match_operand:SI 2 "immediate_operand")]
1848    VCVT_SI_US_N)]
1849  "TARGET_VFP_FP16INST"
1851   rtx op1 = gen_reg_rtx (SImode);
1853   arm_const_bounds (operands[2], 1, 33);
1854   emit_insn (gen_neon_vcvth<sup>_nsi_unspec (op1, operands[1], operands[2]));
1855   emit_move_insn (operands[0], op1);
1856   DONE;
1859 (define_insn "neon_vcvt<vcvth_op>h<sup>si"
1860  [(set
1861    (match_operand:SI 0 "s_register_operand" "=w")
1862    (unspec:SI
1863     [(match_operand:HF 1 "s_register_operand" "w")]
1864     VCVT_HF_US))]
1865  "TARGET_VFP_FP16INST"
1866  "vcvt<vcvth_op>.<sup>%#32.f16\t%0, %1"
1867   [(set_attr "conds" "unconditional")
1868    (set_attr "type" "f_cvtf2i")]
1871 ;; Store multiple insn used in function prologue.
1872 (define_insn "*push_multi_vfp"
1873   [(match_parallel 2 "multi_register_push"
1874     [(set (match_operand:BLK 0 "memory_operand" "=m")
1875           (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
1876                       UNSPEC_PUSH_MULT))])]
1877   "TARGET_32BIT && TARGET_HARD_FLOAT"
1878   "* return vfp_output_vstmd (operands);"
1879   [(set_attr "type" "f_stored")]
1882 ;; VRINT round to integral instructions.
1883 ;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
1884 ;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
1885 ;; rintsf2, rintdf2.
1886 (define_insn "<vrint_pattern><SDF:mode>2"
1887   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1888         (unspec:SDF [(match_operand:SDF 1
1889                          "register_operand" "<F_constraint>")]
1890          VRINT))]
1891   "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1892   "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
1893   [(set_attr "predicable" "<vrint_predicable>")
1894    (set_attr "type" "f_rint<vfp_type>")
1895    (set_attr "conds" "<vrint_conds>")]
1898 ;; Implements the lround, lfloor and lceil optabs.
1899 (define_insn "l<vrint_pattern><su_optab><mode>si2"
1900   [(set (match_operand:SI 0 "register_operand" "=t")
1901         (FIXUORS:SI (unspec:SDF
1902                         [(match_operand:SDF 1
1903                            "register_operand" "<F_constraint>")] VCVT)))]
1904   "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1905   "vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1"
1906   [(set_attr "conds" "unconditional")
1907    (set_attr "type" "f_cvtf2i")]
1910 ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
1911 ;; The 'smax' and 'smin' RTL standard pattern names do not specify which
1912 ;; operand will be returned when both operands are zero (i.e. they may not
1913 ;; honour signed zeroes), or when either operand is NaN.  Therefore GCC
1914 ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
1915 ;; NaNs.
1917 (define_insn "smax<mode>3"
1918   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1919         (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1920                   (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1921   "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1922   "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1923   [(set_attr "type" "f_minmax<vfp_type>")
1924    (set_attr "conds" "unconditional")]
1927 (define_insn "smin<mode>3"
1928   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1929         (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1930                   (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1931   "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1932   "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1933   [(set_attr "type" "f_minmax<vfp_type>")
1934    (set_attr "conds" "unconditional")]
1937 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
1939 (define_insn "neon_<fmaxmin_op>hf"
1940  [(set
1941    (match_operand:HF 0 "s_register_operand" "=w")
1942    (unspec:HF
1943     [(match_operand:HF 1 "s_register_operand" "w")
1944      (match_operand:HF 2 "s_register_operand" "w")]
1945     VMAXMINFNM))]
1946  "TARGET_VFP_FP16INST"
1947  "<fmaxmin_op>.f16\t%0, %1, %2"
1948  [(set_attr "conds" "unconditional")
1949   (set_attr "type" "f_minmaxs")]
1952 (define_insn "<fmaxmin><mode>3"
1953   [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
1954         (unspec:SDF [(match_operand:SDF 1 "s_register_operand" "<F_constraint>")
1955                      (match_operand:SDF 2 "s_register_operand" "<F_constraint>")]
1956                      VMAXMINFNM))]
1957   "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1958   "<fmaxmin_op>.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1959   [(set_attr "type" "f_minmax<vfp_type>")
1960    (set_attr "conds" "unconditional")]
1963 ;; Write Floating-point Status and Control Register.
1964 (define_insn "set_fpscr"
1965   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)]
1966   "TARGET_HARD_FLOAT"
1967   "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
1968   [(set_attr "type" "mrs")])
1970 ;; Read Floating-point Status and Control Register.
1971 (define_insn "get_fpscr"
1972   [(set (match_operand:SI 0 "register_operand" "=r")
1973         (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
1974   "TARGET_HARD_FLOAT"
1975   "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
1976   [(set_attr "type" "mrs")])
1979 ;; Unimplemented insns:
1980 ;; fldm*
1981 ;; fstm*
1982 ;; fmdhr et al (VFPv1)
1983 ;; Support for xD (single precision only) variants.
1984 ;; fmrrs, fmsrr
1986 ;; Split an immediate DF move to two immediate SI moves.
1987 (define_insn_and_split "no_literal_pool_df_immediate"
1988   [(set (match_operand:DF 0 "s_register_operand" "")
1989         (match_operand:DF 1 "const_double_operand" ""))]
1990   "TARGET_THUMB2 && arm_disable_literal_pool
1991   && !(TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
1992        && vfp3_const_double_rtx (operands[1]))"
1993   "#"
1994   "&& !reload_completed"
1995   [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
1996    (set (subreg:SI (match_dup 1) 4) (match_dup 3))
1997    (set (match_dup 0) (match_dup 1))]
1998   "
1999   long buf[2];
2000   real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
2001   operands[2] = GEN_INT ((int) buf[0]);
2002   operands[3] = GEN_INT ((int) buf[1]);
2003   operands[1] = gen_reg_rtx (DFmode);
2004   ")
2006 ;; Split an immediate SF move to one immediate SI move.
2007 (define_insn_and_split "no_literal_pool_sf_immediate"
2008   [(set (match_operand:SF 0 "s_register_operand" "")
2009         (match_operand:SF 1 "const_double_operand" ""))]
2010   "TARGET_THUMB2 && arm_disable_literal_pool
2011   && !(TARGET_HARD_FLOAT && vfp3_const_double_rtx (operands[1]))"
2012   "#"
2013   "&& !reload_completed"
2014   [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
2015    (set (match_dup 0) (match_dup 1))]
2016   "
2017   long buf;
2018   real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
2019   operands[2] = GEN_INT ((int) buf);
2020   operands[1] = gen_reg_rtx (SFmode);
2021   ")