xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/arm/vfp.md (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1;; ARM VFP instruction patterns
2;; Copyright (C) 2003-2020 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.
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;; 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))"
33{
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    }
54}
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")]
72)
73
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, Up, r")
78   (match_operand:HI 1 "general_operand"
79    "rk, I, Py, n, r, m, r, *t, *t, r, Up"))]
80 "TARGET_THUMB2 && TARGET_VFP_BASE
81  && !TARGET_VFP_FP16INST
82  && (register_operand (operands[0], HImode)
83       || register_operand (operands[1], HImode))"
84{
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    case 9:
103      return "vmsr%?\t P0, %1\t@ movhi";
104    case 10:
105      return "vmrs%?\t %0, P0\t@ movhi";
106    default:
107      gcc_unreachable ();
108    }
109}
110 [(set_attr "predicable" "yes")
111  (set_attr "predicable_short_it"
112   "yes, no, yes, no, no, no, no, no, no, no, no")
113  (set_attr "type"
114   "mov_reg, mov_imm, mov_imm, mov_imm, store_4, load_4,\
115    f_mcr, f_mrc, fmov, mve_move, mve_move")
116  (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *, mve, mve")
117  (set_attr "pool_range" "*, *, *, *, *, 4094, *, *, *, *, *")
118  (set_attr "neg_pool_range" "*, *, *, *, *, 250, *, *, *, *, *")
119  (set_attr "length" "2, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4")]
120)
121
122;; Patterns for HI moves which provide more data transfer instructions when FP16
123;; instructions are available.
124(define_insn "*arm_movhi_fp16"
125 [(set
126   (match_operand:HI 0 "nonimmediate_operand"
127    "=r,  r, r, m, r, *t,  r, *t")
128   (match_operand:HI 1 "general_operand"
129    "rIk, K, n, r, mi, r, *t, *t"))]
130 "TARGET_ARM && TARGET_VFP_FP16INST
131  && (register_operand (operands[0], HImode)
132       || register_operand (operands[1], HImode))"
133{
134  switch (which_alternative)
135    {
136    case 0:
137      return "mov%?\t%0, %1\t%@ movhi";
138    case 1:
139      return "mvn%?\t%0, #%B1\t%@ movhi";
140    case 2:
141      return "movw%?\t%0, %L1\t%@ movhi";
142    case 3:
143      return "strh%?\t%1, %0\t%@ movhi";
144    case 4:
145      return "ldrh%?\t%0, %1\t%@ movhi";
146    case 5:
147    case 6:
148      return "vmov.f16\t%0, %1\t%@ int";
149    case 7:
150      return "vmov%?.f32\t%0, %1\t%@ int";
151    default:
152      gcc_unreachable ();
153    }
154}
155 [(set_attr "predicable" "yes, yes, yes, yes, yes, no, no, yes")
156  (set_attr_alternative "type"
157   [(if_then_else
158     (match_operand 1 "const_int_operand" "")
159     (const_string "mov_imm")
160     (const_string "mov_reg"))
161    (const_string "mvn_imm")
162    (const_string "mov_imm")
163    (const_string "store_4")
164    (const_string "load_4")
165    (const_string "f_mcr")
166    (const_string "f_mrc")
167    (const_string "fmov")])
168  (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
169  (set_attr "pool_range" "*, *, *, *, 256, *, *, *")
170  (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *")
171  (set_attr "length" "4")]
172)
173
174(define_insn "*thumb2_movhi_fp16"
175 [(set
176   (match_operand:HI 0 "nonimmediate_operand"
177    "=rk, r, l, r, m, r, *t, r, *t, Up, r")
178   (match_operand:HI 1 "general_operand"
179    "rk, I, Py, n, r, m, r, *t, *t, r, Up"))]
180 "TARGET_THUMB2 && (TARGET_VFP_FP16INST || TARGET_HAVE_MVE)
181  && (register_operand (operands[0], HImode)
182       || register_operand (operands[1], HImode))"
183{
184  switch (which_alternative)
185    {
186    case 0:
187    case 1:
188    case 2:
189      return "mov%?\t%0, %1\t%@ movhi";
190    case 3:
191      return "movw%?\t%0, %L1\t%@ movhi";
192    case 4:
193      return "strh%?\t%1, %0\t%@ movhi";
194    case 5:
195      return "ldrh%?\t%0, %1\t%@ movhi";
196    case 6:
197    case 7:
198      return "vmov.f16\t%0, %1\t%@ int";
199    case 8:
200      return "vmov%?.f32\t%0, %1\t%@ int";
201    case 9:
202      return "vmsr%?\t P0, %1\t%@ movhi";
203    case 10:
204      return "vmrs%?\t%0, P0\t%@ movhi";
205    default:
206      gcc_unreachable ();
207    }
208}
209 [(set_attr "predicable"
210   "yes, yes, yes, yes, yes, yes, no, no, yes, yes, yes")
211  (set_attr "predicable_short_it"
212   "yes, no, yes, no, no, no, no, no, no, no, no")
213  (set_attr "type"
214   "mov_reg, mov_imm, mov_imm, mov_imm, store_4, load_4,\
215    f_mcr, f_mrc, fmov, mve_move, mve_move")
216  (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *, mve, mve")
217  (set_attr "pool_range" "*, *, *, *, *, 4094, *, *, *, *, *")
218  (set_attr "neg_pool_range" "*, *, *, *, *, 250, *, *, *, *, *")
219  (set_attr "length" "2, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4")]
220)
221
222;; SImode moves
223;; ??? For now do not allow loading constants into vfp regs.  This causes
224;; problems because small constants get converted into adds.
225(define_insn "*arm_movsi_vfp"
226  [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv")
227      (match_operand:SI 1 "general_operand"	   "rk, I,K,j,mi,rk,r,*t,*t,*Uvi,*t"))]
228  "TARGET_ARM && TARGET_HARD_FLOAT
229   && (   s_register_operand (operands[0], SImode)
230       || s_register_operand (operands[1], SImode))"
231  "*
232  switch (which_alternative)
233    {
234    case 0: case 1:
235      return \"mov%?\\t%0, %1\";
236    case 2:
237      return \"mvn%?\\t%0, #%B1\";
238    case 3:
239      return \"movw%?\\t%0, %1\";
240    case 4:
241      return \"ldr%?\\t%0, %1\";
242    case 5:
243      return \"str%?\\t%1, %0\";
244    case 6:
245      return \"vmov%?\\t%0, %1\\t%@ int\";
246    case 7:
247      return \"vmov%?\\t%0, %1\\t%@ int\";
248    case 8:
249      return \"vmov%?.f32\\t%0, %1\\t%@ int\";
250    case 9: case 10:
251      return output_move_vfp (operands);
252    default:
253      gcc_unreachable ();
254    }
255  "
256  [(set_attr "predicable" "yes")
257   (set_attr "type" "mov_reg,mov_reg,mvn_imm,mov_imm,load_4,store_4,
258		     f_mcr,f_mrc,fmov,f_loads,f_stores")
259   (set_attr "pool_range"     "*,*,*,*,4096,*,*,*,*,1020,*")
260   (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")]
261)
262
263;; See thumb2.md:thumb2_movsi_insn for an explanation of the split
264;; high/low register alternatives for loads and stores here.
265;; The l/Py alternative should come after r/I to ensure that the short variant
266;; is chosen with length 2 when the instruction is predicated for
267;; arm_restrict_it.
268(define_insn "*thumb2_movsi_vfp"
269  [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r,l,*hk,m,*m,*t,\
270						    r,*t,*t,*Uv, Up, r,Uf,r")
271	(match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,*mi,l,*hk,r,*t,\
272					       *t,*UvTu,*t, r, Up,r,Uf"))]
273  "TARGET_THUMB2 && TARGET_VFP_BASE
274   && (   s_register_operand (operands[0], SImode)
275       || s_register_operand (operands[1], SImode))"
276  "*
277  switch (which_alternative)
278    {
279    case 0:
280    case 1:
281    case 2:
282      return \"mov%?\\t%0, %1\";
283    case 3:
284      return \"mvn%?\\t%0, #%B1\";
285    case 4:
286      return \"movw%?\\t%0, %1\";
287    case 5:
288    case 6:
289      /* Cannot load it directly, split to load it via MOV / MOVT.  */
290      if (!MEM_P (operands[1]) && arm_disable_literal_pool)
291	return \"#\";
292      return \"ldr%?\\t%0, %1\";
293    case 7:
294    case 8:
295      return \"str%?\\t%1, %0\";
296    case 9:
297      return \"vmov%?\\t%0, %1\\t%@ int\";
298    case 10:
299      return \"vmov%?\\t%0, %1\\t%@ int\";
300    case 11:
301      return \"vmov%?.f32\\t%0, %1\\t%@ int\";
302    case 12: case 13:
303      return output_move_vfp (operands);
304    case 14:
305      return \"vmsr\\t P0, %1\";
306    case 15:
307      return \"vmrs\\t %0, P0\";
308    case 16:
309      return \"mcr\\tp10, 7, %1, cr1, cr0, 0\\t @SET_FPSCR\";
310    case 17:
311      return \"mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR\";
312    default:
313      gcc_unreachable ();
314    }
315  "
316  [(set_attr "predicable" "yes")
317   (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,\
318	      no,no,no,no,no")
319   (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_imm,load_4,load_4,\
320	     store_4,store_4,f_mcr,f_mrc,fmov,f_loads,f_stores,mve_move,\
321	     mve_move,mrs,mrs")
322   (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4")
323   (set_attr "pool_range"     "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*,*,*,*,*")
324   (set_attr "arch" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,mve,mve,mve,mve")
325   (set_attr "neg_pool_range" "*,*,*,*,*,   0,   0,*,*,*,*,*,1008,*,*,*,*,*")]
326)
327
328
329;; DImode moves
330
331(define_insn "*movdi_vfp"
332  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,r,r,m,w,!r,w,w, Uv")
333	(match_operand:DI 1 "di_operand"       "r,rDa,Db,Dc,mi,mi,r,r,w,w,UvTu,w"))]
334  "TARGET_32BIT && TARGET_VFP_BASE
335   && (   register_operand (operands[0], DImode)
336       || register_operand (operands[1], DImode))
337   && !((TARGET_NEON || TARGET_HAVE_MVE) && CONST_INT_P (operands[1])
338       && simd_immediate_valid_for_move (operands[1], DImode, NULL, NULL))"
339  "*
340  switch (which_alternative)
341    {
342    case 0:
343    case 1:
344    case 2:
345    case 3:
346      return \"#\";
347    case 4:
348    case 5:
349      /* Cannot load it directly, split to load it via MOV / MOVT.  */
350      if (!MEM_P (operands[1]) && arm_disable_literal_pool)
351	return \"#\";
352      /* Fall through.  */
353    case 6:
354      return output_move_double (operands, true, NULL);
355    case 7:
356      return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\";
357    case 8:
358      return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\";
359    case 9:
360      if (TARGET_VFP_SINGLE || TARGET_HAVE_MVE)
361	return \"vmov%?.f32\\t%0, %1\\t%@ int\;vmov%?.f32\\t%p0, %p1\\t%@ int\";
362      else
363	return \"vmov%?.f64\\t%P0, %P1\\t%@ int\";
364    case 10: case 11:
365      return output_move_vfp (operands);
366    default:
367      gcc_unreachable ();
368    }
369  "
370  [(set_attr "type" "multiple,multiple,multiple,multiple,load_8,load_8,store_8,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored")
371   (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8)
372                              (eq_attr "alternative" "2") (const_int 12)
373                              (eq_attr "alternative" "3") (const_int 16)
374			      (eq_attr "alternative" "4,5,6")
375			       (symbol_ref "arm_count_output_move_double_insns (operands) * 4")
376                              (eq_attr "alternative" "9")
377                               (if_then_else
378                                 (match_test "TARGET_VFP_SINGLE")
379                                 (const_int 8)
380                                 (const_int 4))]
381                              (const_int 4)))
382   (set_attr "predicable"    "yes")
383   (set_attr "arm_pool_range"     "*,*,*,*,1020,4096,*,*,*,*,1020,*")
384   (set_attr "thumb2_pool_range"     "*,*,*,*,1018,4094,*,*,*,*,1018,*")
385   (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
386   (set (attr "ce_count") (symbol_ref "get_attr_length (insn) / 4"))
387   (set_attr "arch"           "t2,any,any,any,a,t2,any,any,any,any,any,any")]
388)
389
390;; HFmode and BFmode moves
391
392(define_insn "*mov<mode>_vfp_<mode>16"
393  [(set (match_operand:HFBF 0 "nonimmediate_operand"
394			  "= ?r,?m,t,r,t,r,t, t, Uj,r")
395	(match_operand:HFBF 1 "general_operand"
396			  "  m,r,t,r,r,t,Dv,Uj,t, F"))]
397  "TARGET_32BIT
398   && (TARGET_VFP_FP16INST || TARGET_HAVE_MVE)
399   && (s_register_operand (operands[0], <MODE>mode)
400       || s_register_operand (operands[1], <MODE>mode))"
401 {
402  switch (which_alternative)
403    {
404    case 0: /* ARM register from memory.  */
405      return \"ldrh%?\\t%0, %1\\t%@ __<fporbf>\";
406    case 1: /* Memory from ARM register.  */
407      return \"strh%?\\t%1, %0\\t%@ __<fporbf>\";
408    case 2: /* S register from S register.  */
409      return \"vmov\\t%0, %1\t%@ __<fporbf>\";
410    case 3: /* ARM register from ARM register.  */
411      return \"mov%?\\t%0, %1\\t%@ __<fporbf>\";
412    case 4: /* S register from ARM register.  */
413    case 5: /* ARM register from S register.  */
414    case 6: /* S register from immediate.  */
415      return \"vmov.f16\\t%0, %1\t%@ __<fporbf>\";
416    case 7: /* S register from memory.  */
417      if (TARGET_HAVE_MVE)
418	return \"vldr.16\\t%0, %1\";
419      else
420	return \"vld1.16\\t{%z0}, %A1\";
421    case 8: /* Memory from S register.  */
422      if (TARGET_HAVE_MVE)
423	return \"vstr.16\\t%1, %0\";
424      else
425	return \"vst1.16\\t{%z1}, %A0\";
426    case 9: /* ARM register from constant.  */
427      {
428	long bits;
429	rtx ops[4];
430
431	bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
432			       <MODE>mode);
433	ops[0] = operands[0];
434	ops[1] = GEN_INT (bits);
435	ops[2] = GEN_INT (bits & 0xff00);
436	ops[3] = GEN_INT (bits & 0x00ff);
437
438	if (arm_arch_thumb2)
439	  output_asm_insn (\"movw\\t%0, %1\", ops);
440	else
441	  output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
442	return \"\";
443       }
444    default:
445      gcc_unreachable ();
446    }
447 }
448  [(set_attr "conds" "*, *, unconditional, *, unconditional, unconditional,\
449		      unconditional, unconditional, unconditional,\
450		      unconditional")
451   (set_attr "predicable" "yes, yes, no, yes, no, no, no, no, no, no")
452   (set_attr "predicable_short_it" "no, no, no, yes,\
453				    no, no, no, no,\
454				    no, no")
455   (set_attr_alternative "type"
456    [(const_string "load_4") (const_string "store_4")
457     (const_string "fmov") (const_string "mov_reg")
458     (const_string "f_mcr") (const_string "f_mrc")
459     (const_string "fconsts") (const_string "neon_load1_1reg")
460     (const_string "neon_store1_1reg")
461     (if_then_else (match_test "arm_arch_thumb2")
462      (const_string "mov_imm")
463      (const_string "multiple"))])
464   (set_attr_alternative "length"
465    [(const_int 4) (const_int 4)
466     (const_int 4) (const_int 4)
467     (const_int 4) (const_int 4)
468     (const_int 4) (const_int 4)
469     (const_int 4)
470     (if_then_else (match_test "arm_arch_thumb2")
471      (const_int 4)
472      (const_int 8))])]
473)
474
475(define_insn "*mov<mode>_vfp_neon"
476  [(set (match_operand:HFBF 0 "nonimmediate_operand" "= t,Um,?r,?m,t,r,t,r,r")
477	(match_operand:HFBF 1 "general_operand"	     " Um, t, m, r,t,r,r,t,F"))]
478  "TARGET_32BIT
479   && TARGET_HARD_FLOAT && TARGET_NEON_FP16
480   && !TARGET_VFP_FP16INST
481   && (   s_register_operand (operands[0], <MODE>mode)
482       || s_register_operand (operands[1], <MODE>mode))"
483  "*
484  switch (which_alternative)
485    {
486    case 0:     /* S register from memory */
487      return \"vld1.16\\t{%z0}, %A1\";
488    case 1:     /* memory from S register */
489      return \"vst1.16\\t{%z1}, %A0\";
490    case 2:     /* ARM register from memory */
491      return \"ldrh\\t%0, %1\\t%@ __<fporbf>\";
492    case 3:     /* memory from ARM register */
493      return \"strh\\t%1, %0\\t%@ __<fporbf>\";
494    case 4:	/* S register from S register */
495      return \"vmov.f32\\t%0, %1\";
496    case 5:	/* ARM register from ARM register */
497      return \"mov\\t%0, %1\\t%@ __<fporbf>\";
498    case 6:	/* S register from ARM register */
499      return \"vmov\\t%0, %1\";
500    case 7:	/* ARM register from S register */
501      return \"vmov\\t%0, %1\";
502    case 8:	/* ARM register from constant */
503      {
504	long bits;
505	rtx ops[4];
506
507	bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
508			       <MODE>mode);
509	ops[0] = operands[0];
510	ops[1] = GEN_INT (bits);
511	ops[2] = GEN_INT (bits & 0xff00);
512	ops[3] = GEN_INT (bits & 0x00ff);
513
514	if (arm_arch_thumb2)
515	  output_asm_insn (\"movw\\t%0, %1\", ops);
516	else
517	  output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
518	return \"\";
519       }
520    default:
521      gcc_unreachable ();
522    }
523  "
524  [(set_attr "conds" "unconditional")
525   (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\
526                     load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
527   (set_attr "length" "4,4,4,4,4,4,4,4,8")]
528)
529
530;; FP16 without element load/store instructions.
531(define_insn "*mov<mode>_vfp"
532  [(set (match_operand:HFBF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
533	(match_operand:HFBF 1 "general_operand"	   " m,r,t,r,r,t,F"))]
534  "TARGET_32BIT
535   && TARGET_HARD_FLOAT
536   && !TARGET_NEON_FP16
537   && !TARGET_VFP_FP16INST
538   && (   s_register_operand (operands[0], <MODE>mode)
539       || s_register_operand (operands[1], <MODE>mode))"
540  "*
541  switch (which_alternative)
542    {
543    case 0:     /* ARM register from memory */
544      return \"ldrh\\t%0, %1\\t%@ __<fporbf>\";
545    case 1:     /* memory from ARM register */
546      return \"strh\\t%1, %0\\t%@ __<fporbf>\";
547    case 2:	/* S register from S register */
548      return \"vmov.f32\\t%0, %1\";
549    case 3:	/* ARM register from ARM register */
550      return \"mov\\t%0, %1\\t%@ __<fporbf>\";
551    case 4:	/* S register from ARM register */
552      return \"vmov\\t%0, %1\";
553    case 5:	/* ARM register from S register */
554      return \"vmov\\t%0, %1\";
555    case 6:	/* ARM register from constant */
556      {
557	long bits;
558	rtx ops[4];
559
560	bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
561			       <MODE>mode);
562	ops[0] = operands[0];
563	ops[1] = GEN_INT (bits);
564	ops[2] = GEN_INT (bits & 0xff00);
565	ops[3] = GEN_INT (bits & 0x00ff);
566
567	if (arm_arch_thumb2)
568	  output_asm_insn (\"movw\\t%0, %1\", ops);
569	else
570	  output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
571	return \"\";
572       }
573    default:
574      gcc_unreachable ();
575    }
576  "
577  [(set_attr "conds" "unconditional")
578   (set_attr "type" "load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
579   (set_attr "length" "4,4,4,4,4,4,8")]
580)
581
582
583;; SFmode moves
584;; Disparage the w<->r cases because reloading an invalid address is
585;; preferable to loading the value via integer registers.
586
587(define_insn "*movsf_vfp"
588  [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t  ,Uv,r ,m,t,r")
589        (match_operand:SF 1 "general_operand"	   " ?r,t,Dv,UvE,t, mE,r,t,r"))]
590  "TARGET_ARM && TARGET_HARD_FLOAT
591   && (   s_register_operand (operands[0], SFmode)
592       || s_register_operand (operands[1], SFmode))"
593  "*
594  switch (which_alternative)
595    {
596    case 0:
597      return \"vmov%?\\t%0, %1\";
598    case 1:
599      return \"vmov%?\\t%0, %1\";
600    case 2:
601      return \"vmov%?.f32\\t%0, %1\";
602    case 3: case 4:
603      return output_move_vfp (operands);
604    case 5:
605      return \"ldr%?\\t%0, %1\\t%@ float\";
606    case 6:
607      return \"str%?\\t%1, %0\\t%@ float\";
608    case 7:
609      return \"vmov%?.f32\\t%0, %1\";
610    case 8:
611      return \"mov%?\\t%0, %1\\t%@ float\";
612    default:
613      gcc_unreachable ();
614    }
615  "
616  [(set_attr "predicable" "yes")
617   (set_attr "type"
618     "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
619   (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
620   (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
621)
622
623(define_insn "*thumb2_movsf_vfp"
624  [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t  ,Uv,r ,m,t,r")
625	(match_operand:SF 1 "hard_sf_operand"	   " ?r,t,Dv,UvHa,t, mHa,r,t,r"))]
626  "TARGET_THUMB2 && TARGET_VFP_BASE
627   && (   s_register_operand (operands[0], SFmode)
628       || s_register_operand (operands[1], SFmode))"
629  "*
630  switch (which_alternative)
631    {
632    case 0:
633      return \"vmov%?\\t%0, %1\";
634    case 1:
635      return \"vmov%?\\t%0, %1\";
636    case 2:
637      return \"vmov%?.f32\\t%0, %1\";
638    case 3: case 4:
639      return output_move_vfp (operands);
640    case 5:
641      return \"ldr%?\\t%0, %1\\t%@ float\";
642    case 6:
643      return \"str%?\\t%1, %0\\t%@ float\";
644    case 7:
645      return \"vmov%?.f32\\t%0, %1\";
646    case 8:
647      return \"mov%?\\t%0, %1\\t%@ float\";
648    default:
649      gcc_unreachable ();
650    }
651  "
652  [(set_attr "predicable" "yes")
653   (set_attr "type"
654     "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
655   (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*")
656   (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
657)
658
659;; DFmode moves
660
661(define_insn "*movdf_vfp"
662  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w  ,Uv,r, m,w,r")
663	(match_operand:DF 1 "soft_df_operand"		   " ?r,w,Dy,G,UvF,w ,mF,r,w,r"))]
664  "TARGET_ARM && TARGET_HARD_FLOAT
665   && (   register_operand (operands[0], DFmode)
666       || register_operand (operands[1], DFmode))"
667  "*
668  {
669    switch (which_alternative)
670      {
671      case 0:
672	return \"vmov%?\\t%P0, %Q1, %R1\";
673      case 1:
674	return \"vmov%?\\t%Q0, %R0, %P1\";
675      case 2:
676	gcc_assert (TARGET_VFP_DOUBLE);
677        return \"vmov%?.f64\\t%P0, %1\";
678      case 3:
679	gcc_assert (TARGET_VFP_DOUBLE);
680	return \"vmov.i64\\t%P0, #0\\t%@ float\";
681      case 4: case 5:
682	return output_move_vfp (operands);
683      case 6: case 7:
684	return output_move_double (operands, true, NULL);
685      case 8:
686	if (TARGET_VFP_SINGLE)
687	  return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
688	else
689	  return \"vmov%?.f64\\t%P0, %P1\";
690      case 9:
691        return \"#\";
692      default:
693	gcc_unreachable ();
694      }
695    }
696  "
697  [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,f_stored,\
698                     load_8,store_8,ffarithd,multiple")
699   (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
700			       (eq_attr "alternative" "8")
701				(if_then_else
702				 (match_test "TARGET_VFP_SINGLE")
703				 (const_int 8)
704				 (const_int 4))]
705			      (const_int 4)))
706   (set_attr "predicable" "yes,yes,yes,no,yes,yes,yes,yes,yes,yes")
707   (set_attr "pool_range" "*,*,*,*,1020,*,1020,*,*,*")
708   (set_attr "neg_pool_range" "*,*,*,*,1004,*,1004,*,*,*")
709   (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
710)
711
712(define_insn "*thumb2_movdf_vfp"
713  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w  ,Uv,r ,m,w,r")
714	(match_operand:DF 1 "hard_df_operand"		   " ?r,w,Dy,G,UvHa,w, mHa,r, w,r"))]
715  "TARGET_THUMB2 && TARGET_VFP_BASE
716   && (   register_operand (operands[0], DFmode)
717       || register_operand (operands[1], DFmode))"
718  "*
719  {
720    switch (which_alternative)
721      {
722      case 0:
723	return \"vmov%?\\t%P0, %Q1, %R1\";
724      case 1:
725	return \"vmov%?\\t%Q0, %R0, %P1\";
726      case 2:
727	gcc_assert (TARGET_VFP_DOUBLE);
728	return \"vmov%?.f64\\t%P0, %1\";
729      case 3:
730	gcc_assert (TARGET_VFP_DOUBLE);
731	return \"vmov.i64\\t%P0, #0\\t%@ float\";
732      case 4: case 5:
733	return output_move_vfp (operands);
734      case 6: case 7: case 9:
735	return output_move_double (operands, true, NULL);
736      case 8:
737	if (TARGET_VFP_SINGLE)
738	  return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
739	else
740	  return \"vmov%?.f64\\t%P0, %P1\";
741      default:
742	abort ();
743      }
744    }
745  "
746  [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,\
747                     f_stored,load_8,store_8,ffarithd,multiple")
748   (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
749			       (eq_attr "alternative" "8")
750				(if_then_else
751				 (match_test "TARGET_VFP_SINGLE")
752				 (const_int 8)
753				 (const_int 4))]
754			      (const_int 4)))
755   (set_attr "pool_range" "*,*,*,*,1018,*,4094,*,*,*")
756   (set_attr "neg_pool_range" "*,*,*,*,1008,*,0,*,*,*")
757   (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
758)
759
760
761;; Conditional move patterns
762
763(define_insn "*movsfcc_vfp"
764  [(set (match_operand:SF   0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
765	(if_then_else:SF
766	  (match_operator   3 "arm_comparison_operator"
767	    [(match_operand 4 "cc_register" "") (const_int 0)])
768	  (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
769	  (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
770  "TARGET_ARM && TARGET_HARD_FLOAT"
771  "@
772   vmov%D3.f32\\t%0, %2
773   vmov%d3.f32\\t%0, %1
774   vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
775   vmov%D3\\t%0, %2
776   vmov%d3\\t%0, %1
777   vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
778   vmov%D3\\t%0, %2
779   vmov%d3\\t%0, %1
780   vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
781   [(set_attr "conds" "use")
782    (set_attr "length" "4,4,8,4,4,8,4,4,8")
783    (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
784)
785
786(define_insn "*thumb2_movsfcc_vfp"
787  [(set (match_operand:SF   0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
788	(if_then_else:SF
789	  (match_operator   3 "arm_comparison_operator"
790	    [(match_operand 4 "cc_register" "") (const_int 0)])
791	  (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
792	  (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
793  "TARGET_THUMB2 && TARGET_VFP_BASE && !arm_restrict_it"
794  "@
795   it\\t%D3\;vmov%D3.f32\\t%0, %2
796   it\\t%d3\;vmov%d3.f32\\t%0, %1
797   ite\\t%D3\;vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
798   it\\t%D3\;vmov%D3\\t%0, %2
799   it\\t%d3\;vmov%d3\\t%0, %1
800   ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
801   it\\t%D3\;vmov%D3\\t%0, %2
802   it\\t%d3\;vmov%d3\\t%0, %1
803   ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
804   [(set_attr "conds" "use")
805    (set_attr "length" "6,6,10,6,6,10,6,6,10")
806    (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
807)
808
809(define_insn "*movdfcc_vfp"
810  [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
811	(if_then_else:DF
812	  (match_operator   3 "arm_comparison_operator"
813	    [(match_operand 4 "cc_register" "") (const_int 0)])
814	  (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
815	  (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
816  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
817  "@
818   vmov%D3.f64\\t%P0, %P2
819   vmov%d3.f64\\t%P0, %P1
820   vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
821   vmov%D3\\t%P0, %Q2, %R2
822   vmov%d3\\t%P0, %Q1, %R1
823   vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
824   vmov%D3\\t%Q0, %R0, %P2
825   vmov%d3\\t%Q0, %R0, %P1
826   vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
827   [(set_attr "conds" "use")
828    (set_attr "length" "4,4,8,4,4,8,4,4,8")
829    (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcr,f_mrrc,f_mrrc,f_mrrc")]
830)
831
832(define_insn "*thumb2_movdfcc_vfp"
833  [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
834	(if_then_else:DF
835	  (match_operator   3 "arm_comparison_operator"
836	    [(match_operand 4 "cc_register" "") (const_int 0)])
837	  (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
838	  (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
839  "TARGET_THUMB2 && TARGET_VFP_BASE && TARGET_VFP_DOUBLE
840   && !arm_restrict_it"
841  "@
842   it\\t%D3\;vmov%D3.f64\\t%P0, %P2
843   it\\t%d3\;vmov%d3.f64\\t%P0, %P1
844   ite\\t%D3\;vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
845   it\t%D3\;vmov%D3\\t%P0, %Q2, %R2
846   it\t%d3\;vmov%d3\\t%P0, %Q1, %R1
847   ite\\t%D3\;vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
848   it\t%D3\;vmov%D3\\t%Q0, %R0, %P2
849   it\t%d3\;vmov%d3\\t%Q0, %R0, %P1
850   ite\\t%D3\;vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
851   [(set_attr "conds" "use")
852    (set_attr "length" "6,6,10,6,6,10,6,6,10")
853    (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcrr,f_mrrc,f_mrrc,f_mrrc")]
854)
855
856
857;; Sign manipulation functions
858
859(define_insn "*abssf2_vfp"
860  [(set (match_operand:SF	  0 "s_register_operand" "=t")
861	(abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
862  "TARGET_32BIT && TARGET_HARD_FLOAT"
863  "vabs%?.f32\\t%0, %1"
864  [(set_attr "predicable" "yes")
865   (set_attr "type" "ffariths")]
866)
867
868(define_insn "*absdf2_vfp"
869  [(set (match_operand:DF	  0 "s_register_operand" "=w")
870	(abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
871  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
872  "vabs%?.f64\\t%P0, %P1"
873  [(set_attr "predicable" "yes")
874   (set_attr "type" "ffarithd")]
875)
876
877(define_insn "*negsf2_vfp"
878  [(set (match_operand:SF	  0 "s_register_operand" "=t,?r")
879	(neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))]
880  "TARGET_32BIT && TARGET_HARD_FLOAT"
881  "@
882   vneg%?.f32\\t%0, %1
883   eor%?\\t%0, %1, #-2147483648"
884  [(set_attr "predicable" "yes")
885   (set_attr "type" "ffariths")]
886)
887
888(define_insn_and_split "*negdf2_vfp"
889  [(set (match_operand:DF	  0 "s_register_operand" "=w,?r,?r")
890	(neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
891  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
892  "@
893   vneg%?.f64\\t%P0, %P1
894   #
895   #"
896  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
897   && arm_general_register_operand (operands[0], DFmode)"
898  [(set (match_dup 0) (match_dup 1))]
899  "
900  if (REGNO (operands[0]) == REGNO (operands[1]))
901    {
902      operands[0] = gen_highpart (SImode, operands[0]);
903      operands[1] = gen_rtx_XOR (SImode, operands[0],
904				 gen_int_mode (0x80000000, SImode));
905    }
906  else
907    {
908      rtx in_hi, in_lo, out_hi, out_lo;
909
910      in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
911			   gen_int_mode (0x80000000, SImode));
912      in_lo = gen_lowpart (SImode, operands[1]);
913      out_hi = gen_highpart (SImode, operands[0]);
914      out_lo = gen_lowpart (SImode, operands[0]);
915
916      if (REGNO (in_lo) == REGNO (out_hi))
917        {
918          emit_insn (gen_rtx_SET (out_lo, in_lo));
919	  operands[0] = out_hi;
920          operands[1] = in_hi;
921        }
922      else
923        {
924          emit_insn (gen_rtx_SET (out_hi, in_hi));
925	  operands[0] = out_lo;
926          operands[1] = in_lo;
927        }
928    }
929  "
930  [(set_attr "predicable" "yes")
931   (set_attr "length" "4,4,8")
932   (set_attr "type" "ffarithd")]
933)
934
935;; ABS and NEG for FP16.
936(define_insn "<absneg_str>hf2"
937  [(set (match_operand:HF 0 "s_register_operand" "=w")
938    (ABSNEG:HF (match_operand:HF 1 "s_register_operand" "w")))]
939 "TARGET_VFP_FP16INST"
940 "v<absneg_str>.f16\t%0, %1"
941  [(set_attr "conds" "unconditional")
942   (set_attr "type" "ffariths")]
943)
944
945(define_expand "neon_vabshf"
946 [(set
947   (match_operand:HF 0 "s_register_operand")
948   (abs:HF (match_operand:HF 1 "s_register_operand")))]
949 "TARGET_VFP_FP16INST"
950{
951  emit_insn (gen_abshf2 (operands[0], operands[1]));
952  DONE;
953})
954
955;; VRND for FP16.
956(define_insn "neon_v<fp16_rnd_str>hf"
957  [(set (match_operand:HF 0 "s_register_operand" "=w")
958    (unspec:HF
959     [(match_operand:HF 1 "s_register_operand" "w")]
960     FP16_RND))]
961 "TARGET_VFP_FP16INST"
962 "<fp16_rnd_insn>.f16\t%0, %1"
963 [(set_attr "conds" "unconditional")
964  (set_attr "type" "neon_fp_round_s")]
965)
966
967(define_insn "neon_vrndihf"
968  [(set (match_operand:HF 0 "s_register_operand" "=w")
969    (unspec:HF
970     [(match_operand:HF 1 "s_register_operand" "w")]
971     UNSPEC_VRNDI))]
972  "TARGET_VFP_FP16INST"
973  "vrintr.f16\t%0, %1"
974 [(set_attr "conds" "unconditional")
975  (set_attr "type" "neon_fp_round_s")]
976)
977
978;; Arithmetic insns
979
980(define_insn "addhf3"
981  [(set
982    (match_operand:HF 0 "s_register_operand" "=w")
983    (plus:HF
984     (match_operand:HF 1 "s_register_operand" "w")
985     (match_operand:HF 2 "s_register_operand" "w")))]
986 "TARGET_VFP_FP16INST"
987 "vadd.f16\t%0, %1, %2"
988  [(set_attr "conds" "unconditional")
989   (set_attr "type" "fadds")]
990)
991
992(define_insn "*addsf3_vfp"
993  [(set (match_operand:SF	   0 "s_register_operand" "=t")
994	(plus:SF (match_operand:SF 1 "s_register_operand" "t")
995		 (match_operand:SF 2 "s_register_operand" "t")))]
996  "TARGET_32BIT && TARGET_HARD_FLOAT"
997  "vadd%?.f32\\t%0, %1, %2"
998  [(set_attr "predicable" "yes")
999   (set_attr "type" "fadds")]
1000)
1001
1002(define_insn "*adddf3_vfp"
1003  [(set (match_operand:DF	   0 "s_register_operand" "=w")
1004	(plus:DF (match_operand:DF 1 "s_register_operand" "w")
1005		 (match_operand:DF 2 "s_register_operand" "w")))]
1006  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1007  "vadd%?.f64\\t%P0, %P1, %P2"
1008  [(set_attr "predicable" "yes")
1009   (set_attr "type" "faddd")]
1010)
1011
1012(define_insn "subhf3"
1013 [(set
1014   (match_operand:HF 0 "s_register_operand" "=w")
1015   (minus:HF
1016    (match_operand:HF 1 "s_register_operand" "w")
1017    (match_operand:HF 2 "s_register_operand" "w")))]
1018 "TARGET_VFP_FP16INST"
1019 "vsub.f16\t%0, %1, %2"
1020  [(set_attr "conds" "unconditional")
1021   (set_attr "type" "fadds")]
1022)
1023
1024(define_insn "*subsf3_vfp"
1025  [(set (match_operand:SF	    0 "s_register_operand" "=t")
1026	(minus:SF (match_operand:SF 1 "s_register_operand" "t")
1027		  (match_operand:SF 2 "s_register_operand" "t")))]
1028  "TARGET_32BIT && TARGET_HARD_FLOAT"
1029  "vsub%?.f32\\t%0, %1, %2"
1030  [(set_attr "predicable" "yes")
1031   (set_attr "type" "fadds")]
1032)
1033
1034(define_insn "*subdf3_vfp"
1035  [(set (match_operand:DF	    0 "s_register_operand" "=w")
1036	(minus:DF (match_operand:DF 1 "s_register_operand" "w")
1037		  (match_operand:DF 2 "s_register_operand" "w")))]
1038  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1039  "vsub%?.f64\\t%P0, %P1, %P2"
1040  [(set_attr "predicable" "yes")
1041   (set_attr "type" "faddd")]
1042)
1043
1044
1045;; Division insns
1046
1047;; FP16 Division.
1048(define_insn "divhf3"
1049  [(set
1050    (match_operand:HF	   0 "s_register_operand" "=w")
1051    (div:HF
1052     (match_operand:HF 1 "s_register_operand" "w")
1053     (match_operand:HF 2 "s_register_operand" "w")))]
1054  "TARGET_VFP_FP16INST"
1055  "vdiv.f16\t%0, %1, %2"
1056  [(set_attr "conds" "unconditional")
1057   (set_attr "type" "fdivs")]
1058)
1059
1060; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1061; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1062; earlier.
1063(define_insn "*divsf3_vfp"
1064  [(set (match_operand:SF	  0 "s_register_operand" "=&t,t")
1065	(div:SF (match_operand:SF 1 "s_register_operand" "t,t")
1066		(match_operand:SF 2 "s_register_operand" "t,t")))]
1067  "TARGET_32BIT && TARGET_HARD_FLOAT"
1068  "vdiv%?.f32\\t%0, %1, %2"
1069  [(set_attr "predicable" "yes")
1070   (set_attr "arch" "*,armv6_or_vfpv3")
1071   (set_attr "type" "fdivs")]
1072)
1073
1074(define_insn "*divdf3_vfp"
1075  [(set (match_operand:DF	  0 "s_register_operand" "=&w,w")
1076	(div:DF (match_operand:DF 1 "s_register_operand" "w,w")
1077		(match_operand:DF 2 "s_register_operand" "w,w")))]
1078  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1079  "vdiv%?.f64\\t%P0, %P1, %P2"
1080  [(set_attr "predicable" "yes")
1081   (set_attr "arch" "*,armv6_or_vfpv3")
1082   (set_attr "type" "fdivd")]
1083)
1084
1085
1086;; Multiplication insns
1087
1088(define_insn "mulhf3"
1089 [(set
1090   (match_operand:HF 0 "s_register_operand" "=w")
1091   (mult:HF (match_operand:HF 1 "s_register_operand" "w")
1092	    (match_operand:HF 2 "s_register_operand" "w")))]
1093  "TARGET_VFP_FP16INST"
1094  "vmul.f16\t%0, %1, %2"
1095  [(set_attr "conds" "unconditional")
1096   (set_attr "type" "fmuls")]
1097)
1098
1099(define_insn "*mulsf3_vfp"
1100  [(set (match_operand:SF	   0 "s_register_operand" "=t")
1101	(mult:SF (match_operand:SF 1 "s_register_operand" "t")
1102		 (match_operand:SF 2 "s_register_operand" "t")))]
1103  "TARGET_32BIT && TARGET_HARD_FLOAT"
1104  "vmul%?.f32\\t%0, %1, %2"
1105  [(set_attr "predicable" "yes")
1106   (set_attr "type" "fmuls")]
1107)
1108
1109(define_insn "*muldf3_vfp"
1110  [(set (match_operand:DF	   0 "s_register_operand" "=w")
1111	(mult:DF (match_operand:DF 1 "s_register_operand" "w")
1112		 (match_operand:DF 2 "s_register_operand" "w")))]
1113  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1114  "vmul%?.f64\\t%P0, %P1, %P2"
1115  [(set_attr "predicable" "yes")
1116   (set_attr "type" "fmuld")]
1117)
1118
1119(define_insn "*mulsf3neghf_vfp"
1120  [(set (match_operand:HF		   0 "s_register_operand" "=t")
1121	(mult:HF (neg:HF (match_operand:HF 1 "s_register_operand" "t"))
1122		 (match_operand:HF	   2 "s_register_operand" "t")))]
1123  "TARGET_VFP_FP16INST && !flag_rounding_math"
1124  "vnmul.f16\\t%0, %1, %2"
1125  [(set_attr "conds" "unconditional")
1126   (set_attr "type" "fmuls")]
1127)
1128
1129(define_insn "*negmulhf3_vfp"
1130  [(set (match_operand:HF		   0 "s_register_operand" "=t")
1131	(neg:HF (mult:HF (match_operand:HF 1 "s_register_operand" "t")
1132		 (match_operand:HF	   2 "s_register_operand" "t"))))]
1133  "TARGET_VFP_FP16INST"
1134  "vnmul.f16\\t%0, %1, %2"
1135  [(set_attr "conds" "unconditional")
1136   (set_attr "type" "fmuls")]
1137)
1138
1139(define_insn "*mulsf3negsf_vfp"
1140  [(set (match_operand:SF		   0 "s_register_operand" "=t")
1141	(mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
1142		 (match_operand:SF	   2 "s_register_operand" "t")))]
1143  "TARGET_32BIT && TARGET_HARD_FLOAT && !flag_rounding_math"
1144  "vnmul%?.f32\\t%0, %1, %2"
1145  [(set_attr "predicable" "yes")
1146   (set_attr "type" "fmuls")]
1147)
1148
1149(define_insn "*negmulsf3_vfp"
1150  [(set (match_operand:SF		   0 "s_register_operand" "=t")
1151	(neg:SF (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1152		 (match_operand:SF	   2 "s_register_operand" "t"))))]
1153  "TARGET_32BIT && TARGET_HARD_FLOAT"
1154  "vnmul%?.f32\\t%0, %1, %2"
1155  [(set_attr "predicable" "yes")
1156   (set_attr "type" "fmuls")]
1157)
1158
1159(define_insn "*muldf3negdf_vfp"
1160  [(set (match_operand:DF		   0 "s_register_operand" "=w")
1161	(mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
1162		 (match_operand:DF	   2 "s_register_operand" "w")))]
1163  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
1164  && !flag_rounding_math"
1165  "vnmul%?.f64\\t%P0, %P1, %P2"
1166  [(set_attr "predicable" "yes")
1167   (set_attr "type" "fmuld")]
1168)
1169
1170(define_insn "*negmuldf3_vfp"
1171  [(set (match_operand:DF		   0 "s_register_operand" "=w")
1172	(neg:DF (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1173		 (match_operand:DF	   2 "s_register_operand" "w"))))]
1174  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1175  "vnmul%?.f64\\t%P0, %P1, %P2"
1176  [(set_attr "predicable" "yes")
1177   (set_attr "type" "fmuld")]
1178)
1179
1180
1181;; Multiply-accumulate insns
1182
1183;; 0 = 1 * 2 + 0
1184(define_insn "*mulsf3addhf_vfp"
1185 [(set (match_operand:HF 0 "s_register_operand" "=t")
1186       (plus:HF
1187	(mult:HF (match_operand:HF 2 "s_register_operand" "t")
1188		 (match_operand:HF 3 "s_register_operand" "t"))
1189	(match_operand:HF 1 "s_register_operand" "0")))]
1190  "TARGET_VFP_FP16INST"
1191  "vmla.f16\\t%0, %2, %3"
1192  [(set_attr "conds" "unconditional")
1193   (set_attr "type" "fmacs")]
1194)
1195
1196(define_insn "*mulsf3addsf_vfp"
1197  [(set (match_operand:SF		    0 "s_register_operand" "=t")
1198	(plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1199			  (match_operand:SF 3 "s_register_operand" "t"))
1200		 (match_operand:SF	    1 "s_register_operand" "0")))]
1201  "TARGET_32BIT && TARGET_HARD_FLOAT"
1202  "vmla%?.f32\\t%0, %2, %3"
1203  [(set_attr "predicable" "yes")
1204   (set_attr "type" "fmacs")]
1205)
1206
1207(define_insn "*muldf3adddf_vfp"
1208  [(set (match_operand:DF		    0 "s_register_operand" "=w")
1209	(plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1210			  (match_operand:DF 3 "s_register_operand" "w"))
1211		 (match_operand:DF	    1 "s_register_operand" "0")))]
1212  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1213  "vmla%?.f64\\t%P0, %P2, %P3"
1214  [(set_attr "predicable" "yes")
1215   (set_attr "type" "fmacd")]
1216)
1217
1218;; 0 = 1 * 2 - 0
1219(define_insn "*mulhf3subhf_vfp"
1220  [(set (match_operand:HF 0 "s_register_operand" "=t")
1221	(minus:HF (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1222			   (match_operand:HF 3 "s_register_operand" "t"))
1223		  (match_operand:HF 1 "s_register_operand" "0")))]
1224  "TARGET_VFP_FP16INST"
1225  "vnmls.f16\\t%0, %2, %3"
1226  [(set_attr "conds" "unconditional")
1227   (set_attr "type" "fmacs")]
1228)
1229
1230(define_insn "*mulsf3subsf_vfp"
1231  [(set (match_operand:SF		     0 "s_register_operand" "=t")
1232	(minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1233			   (match_operand:SF 3 "s_register_operand" "t"))
1234		  (match_operand:SF	     1 "s_register_operand" "0")))]
1235  "TARGET_32BIT && TARGET_HARD_FLOAT"
1236  "vnmls%?.f32\\t%0, %2, %3"
1237  [(set_attr "predicable" "yes")
1238   (set_attr "type" "fmacs")]
1239)
1240
1241(define_insn "*muldf3subdf_vfp"
1242  [(set (match_operand:DF		     0 "s_register_operand" "=w")
1243	(minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1244			   (match_operand:DF 3 "s_register_operand" "w"))
1245		  (match_operand:DF	     1 "s_register_operand" "0")))]
1246  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1247  "vnmls%?.f64\\t%P0, %P2, %P3"
1248  [(set_attr "predicable" "yes")
1249   (set_attr "type" "fmacd")]
1250)
1251
1252;; 0 = -(1 * 2) + 0
1253(define_insn "*mulhf3neghfaddhf_vfp"
1254  [(set (match_operand:HF 0 "s_register_operand" "=t")
1255	(minus:HF (match_operand:HF 1 "s_register_operand" "0")
1256		  (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1257			   (match_operand:HF 3 "s_register_operand" "t"))))]
1258  "TARGET_VFP_FP16INST"
1259  "vmls.f16\\t%0, %2, %3"
1260  [(set_attr "conds" "unconditional")
1261   (set_attr "type" "fmacs")]
1262)
1263
1264(define_insn "*mulsf3negsfaddsf_vfp"
1265  [(set (match_operand:SF		     0 "s_register_operand" "=t")
1266	(minus:SF (match_operand:SF	     1 "s_register_operand" "0")
1267		  (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1268			   (match_operand:SF 3 "s_register_operand" "t"))))]
1269  "TARGET_32BIT && TARGET_HARD_FLOAT"
1270  "vmls%?.f32\\t%0, %2, %3"
1271  [(set_attr "predicable" "yes")
1272   (set_attr "type" "fmacs")]
1273)
1274
1275(define_insn "*fmuldf3negdfadddf_vfp"
1276  [(set (match_operand:DF		     0 "s_register_operand" "=w")
1277	(minus:DF (match_operand:DF	     1 "s_register_operand" "0")
1278		  (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1279			   (match_operand:DF 3 "s_register_operand" "w"))))]
1280  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1281  "vmls%?.f64\\t%P0, %P2, %P3"
1282  [(set_attr "predicable" "yes")
1283   (set_attr "type" "fmacd")]
1284)
1285
1286
1287;; 0 = -(1 * 2) - 0
1288(define_insn "*mulhf3neghfsubhf_vfp"
1289  [(set (match_operand:HF 0 "s_register_operand" "=t")
1290	(minus:HF (mult:HF
1291		   (neg:HF (match_operand:HF 2 "s_register_operand" "t"))
1292		   (match_operand:HF 3 "s_register_operand" "t"))
1293		  (match_operand:HF 1 "s_register_operand" "0")))]
1294  "TARGET_VFP_FP16INST"
1295  "vnmla.f16\\t%0, %2, %3"
1296  [(set_attr "conds" "unconditional")
1297   (set_attr "type" "fmacs")]
1298)
1299
1300(define_insn "*mulsf3negsfsubsf_vfp"
1301  [(set (match_operand:SF		      0 "s_register_operand" "=t")
1302	(minus:SF (mult:SF
1303		    (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
1304		    (match_operand:SF	      3 "s_register_operand" "t"))
1305		  (match_operand:SF	      1 "s_register_operand" "0")))]
1306  "TARGET_32BIT && TARGET_HARD_FLOAT"
1307  "vnmla%?.f32\\t%0, %2, %3"
1308  [(set_attr "predicable" "yes")
1309   (set_attr "type" "fmacs")]
1310)
1311
1312(define_insn "*muldf3negdfsubdf_vfp"
1313  [(set (match_operand:DF		      0 "s_register_operand" "=w")
1314	(minus:DF (mult:DF
1315		    (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
1316		    (match_operand:DF	      3 "s_register_operand" "w"))
1317		  (match_operand:DF	      1 "s_register_operand" "0")))]
1318  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1319  "vnmla%?.f64\\t%P0, %P2, %P3"
1320  [(set_attr "predicable" "yes")
1321   (set_attr "type" "fmacd")]
1322)
1323
1324;; Fused-multiply-accumulate
1325
1326(define_insn "fmahf4"
1327  [(set (match_operand:HF 0 "register_operand" "=w")
1328    (fma:HF
1329     (match_operand:HF 1 "register_operand" "w")
1330     (match_operand:HF 2 "register_operand" "w")
1331     (match_operand:HF 3 "register_operand" "0")))]
1332 "TARGET_VFP_FP16INST"
1333 "vfma.f16\\t%0, %1, %2"
1334 [(set_attr "conds" "unconditional")
1335  (set_attr "type" "ffmas")]
1336)
1337
1338(define_expand "neon_vfmahf"
1339  [(match_operand:HF 0 "s_register_operand")
1340   (match_operand:HF 1 "s_register_operand")
1341   (match_operand:HF 2 "s_register_operand")
1342   (match_operand:HF 3 "s_register_operand")]
1343  "TARGET_VFP_FP16INST"
1344{
1345  emit_insn (gen_fmahf4 (operands[0], operands[2], operands[3],
1346			 operands[1]));
1347  DONE;
1348})
1349
1350(define_insn "fma<SDF:mode>4"
1351  [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1352        (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1353		 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1354		 (match_operand:SDF 3 "register_operand" "0")))]
1355  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>"
1356  "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1357  [(set_attr "predicable" "yes")
1358   (set_attr "type" "ffma<vfp_type>")]
1359)
1360
1361(define_insn "fmsubhf4_fp16"
1362 [(set (match_operand:HF 0 "register_operand" "=w")
1363   (fma:HF
1364    (neg:HF (match_operand:HF 1 "register_operand" "w"))
1365    (match_operand:HF 2 "register_operand" "w")
1366    (match_operand:HF 3 "register_operand" "0")))]
1367 "TARGET_VFP_FP16INST"
1368 "vfms.f16\\t%0, %1, %2"
1369 [(set_attr "conds" "unconditional")
1370  (set_attr "type" "ffmas")]
1371)
1372
1373(define_expand "neon_vfmshf"
1374  [(match_operand:HF 0 "s_register_operand")
1375   (match_operand:HF 1 "s_register_operand")
1376   (match_operand:HF 2 "s_register_operand")
1377   (match_operand:HF 3 "s_register_operand")]
1378  "TARGET_VFP_FP16INST"
1379{
1380  emit_insn (gen_fmsubhf4_fp16 (operands[0], operands[2], operands[3],
1381				operands[1]));
1382  DONE;
1383})
1384
1385(define_insn "*fmsub<SDF:mode>4"
1386  [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1387	(fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1388					     "<F_constraint>"))
1389		 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1390		 (match_operand:SDF 3 "register_operand" "0")))]
1391  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>"
1392  "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1393  [(set_attr "predicable" "yes")
1394   (set_attr "type" "ffma<vfp_type>")]
1395)
1396
1397(define_insn "*fnmsubhf4"
1398  [(set (match_operand:HF 0 "register_operand" "=w")
1399	(fma:HF (match_operand:HF 1 "register_operand" "w")
1400		 (match_operand:HF 2 "register_operand" "w")
1401		 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1402  "TARGET_VFP_FP16INST"
1403  "vfnms.f16\\t%0, %1, %2"
1404  [(set_attr "conds" "unconditional")
1405   (set_attr "type" "ffmas")]
1406)
1407
1408(define_insn "*fnmsub<SDF:mode>4"
1409  [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1410	(fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1411		 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1412		 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1413  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>"
1414  "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1415  [(set_attr "predicable" "yes")
1416   (set_attr "type" "ffma<vfp_type>")]
1417)
1418
1419(define_insn "*fnmaddhf4"
1420  [(set (match_operand:HF 0 "register_operand" "=w")
1421	(fma:HF (neg:HF (match_operand:HF 1 "register_operand" "w"))
1422		 (match_operand:HF 2 "register_operand" "w")
1423		 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1424  "TARGET_VFP_FP16INST"
1425  "vfnma.f16\\t%0, %1, %2"
1426  [(set_attr "conds" "unconditional")
1427   (set_attr "type" "ffmas")]
1428)
1429
1430(define_insn "*fnmadd<SDF:mode>4"
1431  [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1432	(fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1433					       "<F_constraint>"))
1434		 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1435		 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1436  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>"
1437  "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1438  [(set_attr "predicable" "yes")
1439   (set_attr "type" "ffma<vfp_type>")]
1440)
1441
1442
1443;; Conversion routines
1444
1445(define_insn "*extendsfdf2_vfp"
1446  [(set (match_operand:DF		   0 "s_register_operand" "=w")
1447	(float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
1448  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1449  "vcvt%?.f64.f32\\t%P0, %1"
1450  [(set_attr "predicable" "yes")
1451   (set_attr "type" "f_cvt")]
1452)
1453
1454(define_insn "*truncdfsf2_vfp"
1455  [(set (match_operand:SF		   0 "s_register_operand" "=t")
1456	(float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
1457  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1458  "vcvt%?.f32.f64\\t%0, %P1"
1459  [(set_attr "predicable" "yes")
1460   (set_attr "type" "f_cvt")]
1461)
1462
1463(define_insn "extendhfsf2"
1464  [(set (match_operand:SF		   0 "s_register_operand" "=t")
1465	(float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))]
1466  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1467  "vcvtb%?.f32.f16\\t%0, %1"
1468  [(set_attr "predicable" "yes")
1469   (set_attr "type" "f_cvt")]
1470)
1471
1472(define_insn "*truncdfhf2"
1473  [(set (match_operand:HF		   0 "s_register_operand" "=t")
1474	(float_truncate:HF (match_operand:DF 1 "s_register_operand" "w")))]
1475  "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1476  "vcvtb%?.f16.f64\\t%0, %P1"
1477  [(set_attr "predicable" "yes")
1478   (set_attr "type" "f_cvt")]
1479)
1480
1481(define_insn "*extendhfdf2"
1482  [(set (match_operand:DF		   0 "s_register_operand" "=w")
1483	(float_extend:DF (match_operand:HF 1 "s_register_operand" "t")))]
1484  "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1485  "vcvtb%?.f64.f16\\t%P0, %1"
1486  [(set_attr "predicable" "yes")
1487   (set_attr "type" "f_cvt")]
1488)
1489
1490(define_insn "truncsfhf2"
1491  [(set (match_operand:HF		   0 "s_register_operand" "=t")
1492	(float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
1493  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1494  "vcvtb%?.f16.f32\\t%0, %1"
1495  [(set_attr "predicable" "yes")
1496   (set_attr "type" "f_cvt")]
1497)
1498
1499(define_insn "*truncsisf2_vfp"
1500  [(set (match_operand:SI		  0 "s_register_operand" "=t")
1501	(fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1502  "TARGET_32BIT && TARGET_HARD_FLOAT"
1503  "vcvt%?.s32.f32\\t%0, %1"
1504  [(set_attr "predicable" "yes")
1505   (set_attr "type" "f_cvtf2i")]
1506)
1507
1508(define_insn "*truncsidf2_vfp"
1509  [(set (match_operand:SI		  0 "s_register_operand" "=t")
1510	(fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
1511  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1512  "vcvt%?.s32.f64\\t%0, %P1"
1513  [(set_attr "predicable" "yes")
1514   (set_attr "type" "f_cvtf2i")]
1515)
1516
1517
1518(define_insn "fixuns_truncsfsi2"
1519  [(set (match_operand:SI		  0 "s_register_operand" "=t")
1520	(unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1521  "TARGET_32BIT && TARGET_HARD_FLOAT"
1522  "vcvt%?.u32.f32\\t%0, %1"
1523  [(set_attr "predicable" "yes")
1524   (set_attr "type" "f_cvtf2i")]
1525)
1526
1527(define_insn "fixuns_truncdfsi2"
1528  [(set (match_operand:SI		  0 "s_register_operand" "=t")
1529	(unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
1530  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1531  "vcvt%?.u32.f64\\t%0, %P1"
1532  [(set_attr "predicable" "yes")
1533   (set_attr "type" "f_cvtf2i")]
1534)
1535
1536
1537(define_insn "*floatsisf2_vfp"
1538  [(set (match_operand:SF	    0 "s_register_operand" "=t")
1539	(float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1540  "TARGET_32BIT && TARGET_HARD_FLOAT"
1541  "vcvt%?.f32.s32\\t%0, %1"
1542  [(set_attr "predicable" "yes")
1543   (set_attr "type" "f_cvti2f")]
1544)
1545
1546(define_insn "*floatsidf2_vfp"
1547  [(set (match_operand:DF	    0 "s_register_operand" "=w")
1548	(float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1549  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1550  "vcvt%?.f64.s32\\t%P0, %1"
1551  [(set_attr "predicable" "yes")
1552   (set_attr "type" "f_cvti2f")]
1553)
1554
1555
1556(define_insn "floatunssisf2"
1557  [(set (match_operand:SF	    0 "s_register_operand" "=t")
1558	(unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1559  "TARGET_32BIT && TARGET_HARD_FLOAT"
1560  "vcvt%?.f32.u32\\t%0, %1"
1561  [(set_attr "predicable" "yes")
1562   (set_attr "type" "f_cvti2f")]
1563)
1564
1565(define_insn "floatunssidf2"
1566  [(set (match_operand:DF	    0 "s_register_operand" "=w")
1567	(unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1568  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1569  "vcvt%?.f64.u32\\t%P0, %1"
1570  [(set_attr "predicable" "yes")
1571   (set_attr "type" "f_cvti2f")]
1572)
1573
1574
1575;; Sqrt insns.
1576
1577(define_insn "neon_vsqrthf"
1578  [(set (match_operand:HF 0 "s_register_operand" "=w")
1579	(sqrt:HF (match_operand:HF 1 "s_register_operand" "w")))]
1580  "TARGET_VFP_FP16INST"
1581  "vsqrt.f16\t%0, %1"
1582  [(set_attr "conds" "unconditional")
1583   (set_attr "type" "fsqrts")]
1584)
1585
1586(define_insn "neon_vrsqrtshf"
1587  [(set
1588    (match_operand:HF 0 "s_register_operand" "=w")
1589    (unspec:HF [(match_operand:HF 1 "s_register_operand" "w")
1590		(match_operand:HF 2 "s_register_operand" "w")]
1591     UNSPEC_VRSQRTS))]
1592 "TARGET_VFP_FP16INST"
1593 "vrsqrts.f16\t%0, %1, %2"
1594 [(set_attr "conds" "unconditional")
1595  (set_attr "type" "fsqrts")]
1596)
1597
1598; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1599; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1600; earlier.
1601(define_insn "*sqrtsf2_vfp"
1602  [(set (match_operand:SF	   0 "s_register_operand" "=&t,t")
1603	(sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))]
1604  "TARGET_32BIT && TARGET_HARD_FLOAT"
1605  "vsqrt%?.f32\\t%0, %1"
1606  [(set_attr "predicable" "yes")
1607   (set_attr "arch" "*,armv6_or_vfpv3")
1608   (set_attr "type" "fsqrts")]
1609)
1610
1611(define_insn "*sqrtdf2_vfp"
1612  [(set (match_operand:DF	   0 "s_register_operand" "=&w,w")
1613	(sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))]
1614  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1615  "vsqrt%?.f64\\t%P0, %P1"
1616  [(set_attr "predicable" "yes")
1617   (set_attr "arch" "*,armv6_or_vfpv3")
1618   (set_attr "type" "fsqrtd")]
1619)
1620
1621
1622;; Patterns to split/copy vfp condition flags.
1623
1624(define_insn "*movcc_vfp"
1625  [(set (reg CC_REGNUM)
1626	(reg VFPCC_REGNUM))]
1627  "TARGET_32BIT && TARGET_HARD_FLOAT"
1628  "vmrs%?\\tAPSR_nzcv, FPSCR"
1629  [(set_attr "conds" "set")
1630   (set_attr "type" "f_flag")]
1631)
1632
1633(define_insn "push_fpsysreg_insn"
1634  [(set (mem:SI (post_dec:SI (match_operand:SI 0 "s_register_operand" "+&rk")))
1635   (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "n")]
1636		       VUNSPEC_VSTR_VLDR))]
1637  "TARGET_HAVE_FPCXT_CMSE && use_cmse"
1638  {
1639    static char buf[32];
1640    int fp_sysreg_enum = INTVAL (operands[1]);
1641
1642    gcc_assert (IN_RANGE (fp_sysreg_enum, 0, NB_FP_SYSREGS - 1));
1643
1644    snprintf (buf, sizeof (buf), \"vstr%%?\\t%s, [%%0, #-4]!\",
1645	      fp_sysreg_names[fp_sysreg_enum]);
1646    return buf;
1647  }
1648  [(set_attr "predicable" "yes")
1649   (set_attr "type" "store_4")]
1650)
1651
1652(define_insn "pop_fpsysreg_insn"
1653  [(set (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+&rk")))
1654   (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "n")]
1655		       VUNSPEC_VSTR_VLDR))]
1656  "TARGET_HAVE_FPCXT_CMSE && use_cmse"
1657  {
1658    static char buf[32];
1659    int fp_sysreg_enum = INTVAL (operands[1]);
1660
1661    gcc_assert (IN_RANGE (fp_sysreg_enum, 0, NB_FP_SYSREGS - 1));
1662
1663    snprintf (buf, sizeof (buf), \"vldr%%?\\t%s, [%%0], #4\",
1664	      fp_sysreg_names[fp_sysreg_enum]);
1665    return buf;
1666  }
1667  [(set_attr "predicable" "yes")
1668   (set_attr "type" "load_4")]
1669)
1670
1671;; The operands are validated through the clear_multiple_operation
1672;; match_parallel predicate rather than through constraints so enable it only
1673;; after reload.
1674(define_insn "*clear_vfp_multiple"
1675  [(match_parallel 0 "clear_vfp_multiple_operation"
1676     [(unspec_volatile [(const_int 0)]
1677		       VUNSPEC_VSCCLRM_VPR)])]
1678  "TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
1679  {
1680    int num_regs = XVECLEN (operands[0], 0);
1681    char pattern[30];
1682    rtx reg;
1683
1684    strcpy (pattern, \"vscclrm%?\\t{%|\");
1685    if (num_regs > 1)
1686      {
1687	reg = XEXP (XVECEXP (operands[0], 0, 1), 0);
1688	strcat (pattern, reg_names[REGNO (reg)]);
1689	if (num_regs > 2)
1690	  {
1691	    strcat (pattern, \"-%|\");
1692	    reg = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
1693	    strcat (pattern, reg_names[REGNO (reg)]);
1694	  }
1695	strcat (pattern, \", \");
1696      }
1697
1698    strcat (pattern, \"VPR}\");
1699    output_asm_insn (pattern, operands);
1700    return \"\";
1701  }
1702  [(set_attr "predicable" "yes")
1703   (set_attr "type" "mov_reg")]
1704)
1705
1706;; Both this and the next instruction are treated by GCC in the same
1707;; way as a blockage pattern.  That's perhaps stronger than it needs
1708;; to be, but we do not want accesses to the VFP register bank to be
1709;; moved across either instruction.
1710
1711(define_insn "lazy_store_multiple_insn"
1712  [(unspec_volatile
1713    [(mem:BLK (match_operand:SI 0 "s_register_operand" "rk"))]
1714    VUNSPEC_VLSTM)]
1715  "use_cmse && reload_completed"
1716  "vlstm%?\\t%0"
1717  [(set_attr "predicable" "yes")
1718   (set_attr "type" "store_4")]
1719)
1720
1721(define_insn "lazy_load_multiple_insn"
1722  [(unspec_volatile
1723    [(mem:BLK (match_operand:SI 0 "s_register_operand" "rk,rk"))]
1724    VUNSPEC_VLLDM)]
1725  "use_cmse && reload_completed"
1726  "@
1727   vscclrm\\t{vpr}\;vlldm\\t%0
1728   vlldm\\t%0"
1729  [(set_attr "arch" "fix_vlldm,*")
1730   (set_attr "predicable" "no")
1731   (set_attr "length" "8,4")
1732   (set_attr "type" "load_4")]
1733)
1734
1735(define_insn_and_split "*cmpsf_split_vfp"
1736  [(set (reg:CCFP CC_REGNUM)
1737	(compare:CCFP (match_operand:SF 0 "s_register_operand"  "t")
1738		      (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1739  "TARGET_32BIT && TARGET_HARD_FLOAT"
1740  "#"
1741  "TARGET_32BIT && TARGET_HARD_FLOAT"
1742  [(set (reg:CCFP VFPCC_REGNUM)
1743	(compare:CCFP (match_dup 0)
1744		      (match_dup 1)))
1745   (set (reg:CCFP CC_REGNUM)
1746	(reg:CCFP VFPCC_REGNUM))]
1747  ""
1748)
1749
1750(define_insn_and_split "*cmpsf_trap_split_vfp"
1751  [(set (reg:CCFPE CC_REGNUM)
1752	(compare:CCFPE (match_operand:SF 0 "s_register_operand"  "t")
1753		       (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1754  "TARGET_32BIT && TARGET_HARD_FLOAT"
1755  "#"
1756  "TARGET_32BIT && TARGET_HARD_FLOAT"
1757  [(set (reg:CCFPE VFPCC_REGNUM)
1758	(compare:CCFPE (match_dup 0)
1759		       (match_dup 1)))
1760   (set (reg:CCFPE CC_REGNUM)
1761	(reg:CCFPE VFPCC_REGNUM))]
1762  ""
1763)
1764
1765(define_insn_and_split "*cmpdf_split_vfp"
1766  [(set (reg:CCFP CC_REGNUM)
1767	(compare:CCFP (match_operand:DF 0 "s_register_operand"  "w")
1768		      (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1769  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1770  "#"
1771  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1772  [(set (reg:CCFP VFPCC_REGNUM)
1773	(compare:CCFP (match_dup 0)
1774		       (match_dup 1)))
1775   (set (reg:CCFP CC_REGNUM)
1776	(reg:CCFP VFPCC_REGNUM))]
1777  ""
1778)
1779
1780(define_insn_and_split "*cmpdf_trap_split_vfp"
1781  [(set (reg:CCFPE CC_REGNUM)
1782	(compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w")
1783		       (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1784  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1785  "#"
1786  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1787  [(set (reg:CCFPE VFPCC_REGNUM)
1788	(compare:CCFPE (match_dup 0)
1789		       (match_dup 1)))
1790   (set (reg:CCFPE CC_REGNUM)
1791	(reg:CCFPE VFPCC_REGNUM))]
1792  ""
1793)
1794
1795
1796;; Comparison patterns
1797
1798;; In the compare with FP zero case the ARM Architecture Reference Manual
1799;; specifies the immediate to be #0.0.  However, some buggy assemblers only
1800;; accept #0.  We don't want to autodetect broken assemblers, so output #0.
1801(define_insn "*cmpsf_vfp"
1802  [(set (reg:CCFP VFPCC_REGNUM)
1803	(compare:CCFP (match_operand:SF 0 "s_register_operand"  "t,t")
1804		      (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1805  "TARGET_32BIT && TARGET_HARD_FLOAT"
1806  "@
1807   vcmp%?.f32\\t%0, %1
1808   vcmp%?.f32\\t%0, #0"
1809  [(set_attr "predicable" "yes")
1810   (set_attr "type" "fcmps")]
1811)
1812
1813(define_insn "*cmpsf_trap_vfp"
1814  [(set (reg:CCFPE VFPCC_REGNUM)
1815	(compare:CCFPE (match_operand:SF 0 "s_register_operand"  "t,t")
1816		       (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1817  "TARGET_32BIT && TARGET_HARD_FLOAT"
1818  "@
1819   vcmpe%?.f32\\t%0, %1
1820   vcmpe%?.f32\\t%0, #0"
1821  [(set_attr "predicable" "yes")
1822   (set_attr "type" "fcmps")]
1823)
1824
1825(define_insn "*cmpdf_vfp"
1826  [(set (reg:CCFP VFPCC_REGNUM)
1827	(compare:CCFP (match_operand:DF 0 "s_register_operand"  "w,w")
1828		      (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1829  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1830  "@
1831   vcmp%?.f64\\t%P0, %P1
1832   vcmp%?.f64\\t%P0, #0"
1833  [(set_attr "predicable" "yes")
1834   (set_attr "type" "fcmpd")]
1835)
1836
1837(define_insn "*cmpdf_trap_vfp"
1838  [(set (reg:CCFPE VFPCC_REGNUM)
1839	(compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w,w")
1840		       (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1841  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1842  "@
1843   vcmpe%?.f64\\t%P0, %P1
1844   vcmpe%?.f64\\t%P0, #0"
1845  [(set_attr "predicable" "yes")
1846   (set_attr "type" "fcmpd")]
1847)
1848
1849;; Fixed point to floating point conversions.
1850(define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1851  [(set (match_operand:SF 0 "s_register_operand" "=t")
1852	(mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
1853		 (match_operand 2
1854			"const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1855  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1856  "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2"
1857  [(set_attr "predicable" "yes")
1858   (set_attr "type" "f_cvti2f")]
1859)
1860
1861;; Not the ideal way of implementing this. Ideally we would be able to split
1862;; this into a move to a DP register and then a vcvt.f64.i32
1863(define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1864  [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1865	(mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
1866		 (match_operand 2
1867		     "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
1868  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
1869  && !TARGET_VFP_SINGLE"
1870  "@
1871  vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1872  vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1873  vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1874  [(set_attr "predicable" "yes")
1875   (set_attr "ce_count" "2")
1876   (set_attr "type" "f_cvti2f")
1877   (set_attr "length" "8")]
1878)
1879
1880(define_insn "*combine_vcvtf2i"
1881  [(set (match_operand:SI 0 "s_register_operand" "=t")
1882	(fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0")
1883				 (match_operand 2
1884				 "const_double_vcvt_power_of_two" "Dp")))))]
1885  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1886  "vcvt%?.s32.f32\\t%0, %1, %v2"
1887  [(set_attr "predicable" "yes")
1888   (set_attr "type" "f_cvtf2i")]
1889 )
1890
1891;; FP16 conversions.
1892(define_insn "neon_vcvth<sup>hf"
1893 [(set (match_operand:HF 0 "s_register_operand" "=w")
1894   (unspec:HF
1895    [(match_operand:SI 1 "s_register_operand" "w")]
1896    VCVTH_US))]
1897 "TARGET_VFP_FP16INST"
1898 "vcvt.f16.<sup>%#32\t%0, %1"
1899 [(set_attr "conds" "unconditional")
1900  (set_attr "type" "f_cvti2f")]
1901)
1902
1903(define_insn "neon_vcvth<sup>si"
1904 [(set (match_operand:SI 0 "s_register_operand" "=w")
1905   (unspec:SI
1906    [(match_operand:HF 1 "s_register_operand" "w")]
1907    VCVTH_US))]
1908 "TARGET_VFP_FP16INST"
1909 "vcvt.<sup>%#32.f16\t%0, %1"
1910 [(set_attr "conds" "unconditional")
1911  (set_attr "type" "f_cvtf2i")]
1912)
1913
1914;; The neon_vcvth<sup>_nhf patterns are used to generate the instruction for the
1915;; vcvth_n_f16_<sup>32 arm_fp16 intrinsics.  They are complicated by the
1916;; hardware requirement that the source and destination registers are the same
1917;; despite having different machine modes.  The approach is to use a temporary
1918;; register for the conversion and move that to the correct destination.
1919
1920;; Generate an unspec pattern for the intrinsic.
1921(define_insn "neon_vcvth<sup>_nhf_unspec"
1922 [(set
1923   (match_operand:SI 0 "s_register_operand" "=w")
1924   (unspec:SI
1925    [(match_operand:SI 1 "s_register_operand" "0")
1926     (match_operand:SI 2 "immediate_operand" "i")]
1927    VCVT_HF_US_N))
1928 (set
1929  (match_operand:HF 3 "s_register_operand" "=w")
1930  (float_truncate:HF (float:SF (match_dup 0))))]
1931 "TARGET_VFP_FP16INST"
1932{
1933  arm_const_bounds (operands[2], 1, 33);
1934  return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1935}
1936  [(set_attr "conds" "unconditional")
1937   (set_attr "type" "f_cvti2f")]
1938)
1939
1940;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1941(define_expand "neon_vcvth<sup>_nhf"
1942 [(match_operand:HF 0 "s_register_operand")
1943  (unspec:HF [(match_operand:SI 1 "s_register_operand")
1944	      (match_operand:SI 2 "immediate_operand")]
1945   VCVT_HF_US_N)]
1946"TARGET_VFP_FP16INST"
1947{
1948  rtx op1 = gen_reg_rtx (SImode);
1949
1950  arm_const_bounds (operands[2], 1, 33);
1951
1952  emit_move_insn (op1, operands[1]);
1953  emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2],
1954					     operands[0]));
1955  DONE;
1956})
1957
1958;; The neon_vcvth<sup>_nsi patterns are used to generate the instruction for the
1959;; vcvth_n_<sup>32_f16 arm_fp16 intrinsics.  They have the same restrictions and
1960;; are implemented in the same way as the neon_vcvth<sup>_nhf patterns.
1961
1962;; Generate an unspec pattern, constraining the registers.
1963(define_insn "neon_vcvth<sup>_nsi_unspec"
1964 [(set (match_operand:SI 0 "s_register_operand" "=w")
1965   (unspec:SI
1966    [(fix:SI
1967      (fix:SF
1968       (float_extend:SF
1969	(match_operand:HF 1 "s_register_operand" "w"))))
1970     (match_operand:SI 2 "immediate_operand" "i")]
1971    VCVT_SI_US_N))]
1972 "TARGET_VFP_FP16INST"
1973{
1974  arm_const_bounds (operands[2], 1, 33);
1975  return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1976}
1977  [(set_attr "conds" "unconditional")
1978   (set_attr "type" "f_cvtf2i")]
1979)
1980
1981;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1982(define_expand "neon_vcvth<sup>_nsi"
1983 [(match_operand:SI 0 "s_register_operand")
1984  (unspec:SI
1985   [(match_operand:HF 1 "s_register_operand")
1986    (match_operand:SI 2 "immediate_operand")]
1987   VCVT_SI_US_N)]
1988 "TARGET_VFP_FP16INST"
1989{
1990  rtx op1 = gen_reg_rtx (SImode);
1991
1992  arm_const_bounds (operands[2], 1, 33);
1993  emit_insn (gen_neon_vcvth<sup>_nsi_unspec (op1, operands[1], operands[2]));
1994  emit_move_insn (operands[0], op1);
1995  DONE;
1996})
1997
1998(define_insn "neon_vcvt<vcvth_op>h<sup>si"
1999 [(set
2000   (match_operand:SI 0 "s_register_operand" "=w")
2001   (unspec:SI
2002    [(match_operand:HF 1 "s_register_operand" "w")]
2003    VCVT_HF_US))]
2004 "TARGET_VFP_FP16INST"
2005 "vcvt<vcvth_op>.<sup>%#32.f16\t%0, %1"
2006  [(set_attr "conds" "unconditional")
2007   (set_attr "type" "f_cvtf2i")]
2008)
2009
2010;; Store multiple insn used in function prologue.
2011(define_insn "*push_multi_vfp"
2012  [(match_parallel 2 "multi_register_push"
2013    [(set (match_operand:BLK 0 "memory_operand" "=m")
2014	  (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
2015		      UNSPEC_PUSH_MULT))])]
2016  "TARGET_32BIT && TARGET_VFP_BASE"
2017  "* return vfp_output_vstmd (operands);"
2018  [(set_attr "type" "f_stored")]
2019)
2020
2021;; VRINT round to integral instructions.
2022;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
2023;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
2024;; rintsf2, rintdf2.
2025(define_insn "<vrint_pattern><SDF:mode>2"
2026  [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
2027        (unspec:SDF [(match_operand:SDF 1
2028		         "register_operand" "<F_constraint>")]
2029         VRINT))]
2030  "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2031  "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
2032  [(set_attr "predicable" "<vrint_predicable>")
2033   (set_attr "type" "f_rint<vfp_type>")
2034   (set_attr "conds" "<vrint_conds>")]
2035)
2036
2037;; Implements the lround, lfloor and lceil optabs.
2038(define_insn "l<vrint_pattern><su_optab><mode>si2"
2039  [(set (match_operand:SI 0 "register_operand" "=t")
2040        (FIXUORS:SI (unspec:SDF
2041                        [(match_operand:SDF 1
2042                           "register_operand" "<F_constraint>")] VCVT)))]
2043  "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2044  "vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1"
2045  [(set_attr "conds" "unconditional")
2046   (set_attr "type" "f_cvtf2i")]
2047)
2048
2049;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
2050;; The 'smax' and 'smin' RTL standard pattern names do not specify which
2051;; operand will be returned when both operands are zero (i.e. they may not
2052;; honour signed zeroes), or when either operand is NaN.  Therefore GCC
2053;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
2054;; NaNs.
2055
2056(define_insn "smax<mode>3"
2057  [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
2058        (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
2059		  (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
2060  "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2061  "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2062  [(set_attr "type" "f_minmax<vfp_type>")
2063   (set_attr "conds" "unconditional")]
2064)
2065
2066(define_insn "smin<mode>3"
2067  [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
2068        (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
2069		  (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
2070  "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2071  "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2072  [(set_attr "type" "f_minmax<vfp_type>")
2073   (set_attr "conds" "unconditional")]
2074)
2075
2076;; Scalar forms for the IEEE-754 fmax()/fmin() functions
2077
2078(define_insn "neon_<fmaxmin_op>hf"
2079 [(set
2080   (match_operand:HF 0 "s_register_operand" "=w")
2081   (unspec:HF
2082    [(match_operand:HF 1 "s_register_operand" "w")
2083     (match_operand:HF 2 "s_register_operand" "w")]
2084    VMAXMINFNM))]
2085 "TARGET_VFP_FP16INST"
2086 "<fmaxmin_op>.f16\t%0, %1, %2"
2087 [(set_attr "conds" "unconditional")
2088  (set_attr "type" "f_minmaxs")]
2089)
2090
2091(define_insn "<fmaxmin><mode>3"
2092  [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
2093	(unspec:SDF [(match_operand:SDF 1 "s_register_operand" "<F_constraint>")
2094		     (match_operand:SDF 2 "s_register_operand" "<F_constraint>")]
2095		     VMAXMINFNM))]
2096  "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2097  "<fmaxmin_op>.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2098  [(set_attr "type" "f_minmax<vfp_type>")
2099   (set_attr "conds" "unconditional")]
2100)
2101
2102;; Write Floating-point Status and Control Register.
2103(define_insn "set_fpscr"
2104  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
2105    VUNSPEC_SET_FPSCR)]
2106  "TARGET_VFP_BASE"
2107  "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
2108  [(set_attr "type" "mrs")])
2109
2110;; Read Floating-point Status and Control Register.
2111(define_insn "get_fpscr"
2112  [(set (match_operand:SI 0 "register_operand" "=r")
2113    (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
2114  "TARGET_VFP_BASE"
2115  "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
2116  [(set_attr "type" "mrs")])
2117
2118
2119;; Unimplemented insns:
2120;; fldm*
2121;; fstm*
2122;; fmdhr et al (VFPv1)
2123;; Support for xD (single precision only) variants.
2124;; fmrrs, fmsrr
2125
2126;; Load a DF immediate via GPR (where combinations of MOV and MOVT can be used)
2127;; and then move it into a VFP register.
2128(define_insn_and_split "no_literal_pool_df_immediate"
2129  [(set (match_operand:DF 0 "s_register_operand" "=w")
2130	(match_operand:DF 1 "const_double_operand" "F"))
2131   (clobber (match_operand:DF 2 "s_register_operand" "=r"))]
2132  "arm_disable_literal_pool
2133   && TARGET_VFP_BASE
2134   && !arm_const_double_rtx (operands[1])
2135   && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1]))"
2136  "#"
2137  ""
2138  [(const_int 0)]
2139{
2140  long buf[2];
2141  int order = BYTES_BIG_ENDIAN ? 1 : 0;
2142  real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
2143  unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
2144  ival |= (zext_hwi (buf[1 - order], 32) << 32);
2145  rtx cst = gen_int_mode (ival, DImode);
2146  emit_move_insn (simplify_gen_subreg (DImode, operands[2], DFmode, 0), cst);
2147  emit_move_insn (operands[0], operands[2]);
2148  DONE;
2149}
2150)
2151
2152;; Load a SF immediate via GPR (where combinations of MOV and MOVT can be used)
2153;; and then move it into a VFP register.
2154(define_insn_and_split "no_literal_pool_sf_immediate"
2155  [(set (match_operand:SF 0 "s_register_operand" "=t")
2156	(match_operand:SF 1 "const_double_operand" "E"))
2157   (clobber (match_operand:SF 2 "s_register_operand" "=r"))]
2158  "arm_disable_literal_pool
2159   && TARGET_VFP_BASE
2160   && !vfp3_const_double_rtx (operands[1])"
2161  "#"
2162  ""
2163  [(const_int 0)]
2164{
2165  long buf;
2166  real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
2167  rtx cst = gen_int_mode (buf, SImode);
2168  emit_move_insn (simplify_gen_subreg (SImode, operands[2], SFmode, 0), cst);
2169  emit_move_insn (operands[0], operands[2]);
2170  DONE;
2171}
2172)
2173
2174;; CDE instructions using FPU/MVE S/D registers
2175
2176(define_insn "arm_vcx1<mode>"
2177  [(set (match_operand:SIDI 0 "register_operand" "=t")
2178	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
2179		      (match_operand:SI 2 "const_int_vcde1_operand" "i")]
2180	 UNSPEC_VCDE))]
2181  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
2182  "vcx1\\tp%c1, %<V_reg>0, #%c2"
2183  [(set_attr "type" "coproc")]
2184)
2185
2186(define_insn "arm_vcx1a<mode>"
2187  [(set (match_operand:SIDI 0 "register_operand" "=t")
2188	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
2189		      (match_operand:SIDI 2 "register_operand" "0")
2190		      (match_operand:SI 3 "const_int_vcde1_operand" "i")]
2191	 UNSPEC_VCDEA))]
2192  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
2193  "vcx1a\\tp%c1, %<V_reg>0, #%c3"
2194  [(set_attr "type" "coproc")]
2195)
2196
2197(define_insn "arm_vcx2<mode>"
2198  [(set (match_operand:SIDI 0 "register_operand" "=t")
2199	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
2200		      (match_operand:SIDI 2 "register_operand" "t")
2201		      (match_operand:SI 3 "const_int_vcde2_operand" "i")]
2202	 UNSPEC_VCDE))]
2203  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
2204  "vcx2\\tp%c1, %<V_reg>0, %<V_reg>2, #%c3"
2205  [(set_attr "type" "coproc")]
2206)
2207
2208(define_insn "arm_vcx2a<mode>"
2209  [(set (match_operand:SIDI 0 "register_operand" "=t")
2210	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
2211		      (match_operand:SIDI 2 "register_operand" "0")
2212		      (match_operand:SIDI 3 "register_operand" "t")
2213		      (match_operand:SI 4 "const_int_vcde2_operand" "i")]
2214	 UNSPEC_VCDEA))]
2215  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
2216  "vcx2a\\tp%c1, %<V_reg>0, %<V_reg>3, #%c4"
2217  [(set_attr "type" "coproc")]
2218)
2219
2220(define_insn "arm_vcx3<mode>"
2221  [(set (match_operand:SIDI 0 "register_operand" "=t")
2222	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
2223		      (match_operand:SIDI 2 "register_operand" "t")
2224		      (match_operand:SIDI 3 "register_operand" "t")
2225		      (match_operand:SI 4 "const_int_vcde3_operand" "i")]
2226	 UNSPEC_VCDE))]
2227  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
2228  "vcx3\\tp%c1, %<V_reg>0, %<V_reg>2, %<V_reg>3, #%c4"
2229  [(set_attr "type" "coproc")]
2230)
2231
2232(define_insn "arm_vcx3a<mode>"
2233  [(set (match_operand:SIDI 0 "register_operand" "=t")
2234	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
2235		      (match_operand:SIDI 2 "register_operand" "0")
2236		      (match_operand:SIDI 3 "register_operand" "t")
2237		      (match_operand:SIDI 4 "register_operand" "t")
2238		      (match_operand:SI 5 "const_int_vcde3_operand" "i")]
2239	 UNSPEC_VCDEA))]
2240  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
2241  "vcx3a\\tp%c1, %<V_reg>0, %<V_reg>3, %<V_reg>4, #%c5"
2242  [(set_attr "type" "coproc")]
2243)
2244