[PR testsuite/116860] Testsuite adjustment for recently added tests
[official-gcc.git] / gcc / config / arm / vfp.md
blob379f5f7b3dc9398f401d582b56be4bb94629c3cf
1 ;; ARM VFP instruction patterns
2 ;; Copyright (C) 2003-2025 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.  */
21 ;; Patterns for HI moves which provide more data transfer instructions when VFP
22 ;; support is enabled.
23 (define_insn "*arm_movhi_vfp"
24  [(set
25    (match_operand:HI 0 "nonimmediate_operand"
26     "=rk,  r, r, m, r, *t,  r, *t")
27    (match_operand:HI 1 "general_operand"
28     "rIk, K, n, r, mi, r, *t, *t"))]
29  "TARGET_ARM && TARGET_HARD_FLOAT
30   && !TARGET_VFP_FP16INST
31   && (register_operand (operands[0], HImode)
32        || register_operand (operands[1], HImode))"
34   switch (which_alternative)
35     {
36     case 0:
37       return "mov%?\t%0, %1\t%@ movhi";
38     case 1:
39       return "mvn%?\t%0, #%B1\t%@ movhi";
40     case 2:
41       return "movw%?\t%0, %L1\t%@ movhi";
42     case 3:
43       return "strh%?\t%1, %0\t%@ movhi";
44     case 4:
45       return "ldrh%?\t%0, %1\t%@ movhi";
46     case 5:
47     case 6:
48       return "vmov%?\t%0, %1\t%@ int";
49     case 7:
50       return "vmov%?.f32\t%0, %1\t%@ int";
51     default:
52       gcc_unreachable ();
53     }
55  [(set_attr "predicable" "yes")
56   (set_attr_alternative "type"
57    [(if_then_else
58      (match_operand 1 "const_int_operand" "")
59      (const_string "mov_imm")
60      (const_string "mov_reg"))
61     (const_string "mvn_imm")
62     (const_string "mov_imm")
63     (const_string "store_4")
64     (const_string "load_4")
65     (const_string "f_mcr")
66     (const_string "f_mrc")
67     (const_string "fmov")])
68   (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
69   (set_attr "pool_range" "*, *, *, *, 256, *, *, *")
70   (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *")
71   (set_attr "length" "4")]
74 (define_insn "*thumb2_movhi_vfp"
75  [(set
76    (match_operand: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))"
85   switch (which_alternative)
86     {
87     case 0:
88     case 2:
89       return "mov%?\t%0, %1\t%@ movhi";
90     case 1:
91       if (VALID_MVE_PRED_MODE (<MODE>mode))
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     }
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")]
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))"
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     }
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")]
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))"
189   switch (which_alternative)
190     {
191     case 0:
192     case 2:
193       return "mov%?\t%0, %1\t%@ movhi";
194     case 1:
195       if (VALID_MVE_PRED_MODE (<MODE>mode))
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     }
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")]
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,*")]
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,*,*,*,*,*")]
339 ;; DImode moves
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 && !TARGET_HAVE_MVE")
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")]
400 ;; HFmode and BFmode moves
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))"
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];
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);
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     }
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))])]
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];
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);
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")]
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];
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);
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")]
593 ;; SFmode moves
594 ;; Disparage the w<->r cases because reloading an invalid address is
595 ;; preferable to loading the value via integer registers.
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,*,*,*")]
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,*,*,*")]
669 ;; DFmode moves
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")]
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 && !TARGET_HAVE_MVE)
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 && !TARGET_HAVE_MVE")
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")]
771 ;; Conditional move patterns
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")]
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")]
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")]
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")]
867 ;; Sign manipulation functions
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")]
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")]
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")]
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;
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]);
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")]
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")]
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"
961   emit_insn (gen_abshf2 (operands[0], operands[1]));
962   DONE;
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")]
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")]
988 ;; Arithmetic insns
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")]
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")]
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")]
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")]
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")]
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")]
1055 ;; Division insns
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")]
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")]
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")]
1096 ;; Multiplication insns
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
1191 ;; Multiply-accumulate insns
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
1334 ;; Fused-multiply-accumulate
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")]
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"
1355   emit_insn (gen_fmahf4 (operands[0], operands[2], operands[3],
1356                          operands[1]));
1357   DONE;
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>")]
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")]
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"
1390   emit_insn (gen_fmsubhf4_fp16 (operands[0], operands[2], operands[3],
1391                                 operands[1]));
1392   DONE;
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>")]
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")]
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>")]
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")]
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>")]
1453 ;; Conversion routines
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
1585 ;; Sqrt insns.
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")]
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")]
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")]
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")]
1632 ;; Patterns to split/copy vfp condition flags.
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")]
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]);
1652     gcc_assert (IN_RANGE (fp_sysreg_enum, 0, NB_FP_SYSREGS - 1));
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")]
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]);
1671     gcc_assert (IN_RANGE (fp_sysreg_enum, 0, NB_FP_SYSREGS - 1));
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")]
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;
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       }
1708     strcat (pattern, \"VPR}\");
1709     output_asm_insn (pattern, operands);
1710     return \"\";
1711   }
1712   [(set_attr "predicable" "yes")
1713    (set_attr "type" "mov_reg")]
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.
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")]
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")]
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   ""
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   ""
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   ""
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   ""
1806 ;; Comparison patterns
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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.
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"
1943   arm_const_bounds (operands[2], 1, 33);
1944   return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1946   [(set_attr "conds" "unconditional")
1947    (set_attr "type" "f_cvti2f")]
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"
1958   rtx op1 = gen_reg_rtx (SImode);
1960   arm_const_bounds (operands[2], 1, 33);
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;
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.
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"
1984   arm_const_bounds (operands[2], 1, 33);
1985   return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1987   [(set_attr "conds" "unconditional")
1988    (set_attr "type" "f_cvtf2i")]
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"
2000   rtx op1 = gen_reg_rtx (SImode);
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;
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")]
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")]
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>")]
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")]
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.
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")]
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")]
2086 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
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")]
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")]
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")])
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")])
2129 ;; Unimplemented insns:
2130 ;; fldm*
2131 ;; fstm*
2132 ;; fmdhr et al (VFPv1)
2133 ;; Support for xD (single precision only) variants.
2134 ;; fmrrs, fmsrr
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)]
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;
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)]
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;
2185 ;; CDE instructions using FPU/MVE S/D registers
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")]
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")]
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")]
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")]
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")]
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")]