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