2013-09-10 Christophe Lyon <christophe.lyon@linaro.org>
[official-gcc.git] / gcc-4_8-branch / gcc / config / arm / vfp.md
blobef8777a900bfdc539b3d688665d815e61873f693
1 ;; ARM VFP instruction patterns
2 ;; Copyright (C) 2003-2013 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 ;; SImode moves
22 ;; ??? For now do not allow loading constants into vfp regs.  This causes
23 ;; problems because small constants get converted into adds.
24 (define_insn "*arm_movsi_vfp"
25   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv")
26       (match_operand:SI 1 "general_operand"        "rk, I,K,j,mi,rk,r,*t,*t,*Uvi,*t"))]
27   "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
28    && (   s_register_operand (operands[0], SImode)
29        || s_register_operand (operands[1], SImode))"
30   "*
31   switch (which_alternative)
32     {
33     case 0: case 1:
34       return \"mov%?\\t%0, %1\";
35     case 2:
36       return \"mvn%?\\t%0, #%B1\";
37     case 3:
38       return \"movw%?\\t%0, %1\";
39     case 4:
40       return \"ldr%?\\t%0, %1\";
41     case 5:
42       return \"str%?\\t%1, %0\";
43     case 6:
44       return \"fmsr%?\\t%0, %1\\t%@ int\";
45     case 7:
46       return \"fmrs%?\\t%0, %1\\t%@ int\";
47     case 8:
48       return \"fcpys%?\\t%0, %1\\t%@ int\";
49     case 9: case 10:
50       return output_move_vfp (operands);
51     default:
52       gcc_unreachable ();
53     }
54   "
55   [(set_attr "predicable" "yes")
56    (set_attr "type" "mov_reg,mov_reg,mvn_imm,mov_imm,load1,store1,r_2_f,f_2_r,fcpys,f_loads,f_stores")
57    (set_attr "neon_type" "*,*,*,*,*,*,neon_mcr,neon_mrc,neon_vmov,*,*")
58    (set_attr "pool_range"     "*,*,*,*,4096,*,*,*,*,1020,*")
59    (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")]
62 ;; See thumb2.md:thumb2_movsi_insn for an explanation of the split
63 ;; high/low register alternatives for loads and stores here.
64 ;; The l/Py alternative should come after r/I to ensure that the short variant
65 ;; is chosen with length 2 when the instruction is predicated for
66 ;; arm_restrict_it.
67 (define_insn "*thumb2_movsi_vfp"
68   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r, l,*hk,m, *m,*t, r,*t,*t,  *Uv")
69         (match_operand:SI 1 "general_operand"      "rk,I,Py,K,j,mi,*mi,l,*hk, r,*t,*t,*Uvi,*t"))]
70   "TARGET_THUMB2 && TARGET_VFP && TARGET_HARD_FLOAT
71    && (   s_register_operand (operands[0], SImode)
72        || s_register_operand (operands[1], SImode))"
73   "*
74   switch (which_alternative)
75     {
76     case 0:
77     case 1:
78     case 2:
79       return \"mov%?\\t%0, %1\";
80     case 3:
81       return \"mvn%?\\t%0, #%B1\";
82     case 4:
83       return \"movw%?\\t%0, %1\";
84     case 5:
85     case 6:
86       return \"ldr%?\\t%0, %1\";
87     case 7:
88     case 8:
89       return \"str%?\\t%1, %0\";
90     case 9:
91       return \"fmsr%?\\t%0, %1\\t%@ int\";
92     case 10:
93       return \"fmrs%?\\t%0, %1\\t%@ int\";
94     case 11:
95       return \"fcpys%?\\t%0, %1\\t%@ int\";
96     case 12: case 13:
97       return output_move_vfp (operands);
98     default:
99       gcc_unreachable ();
100     }
101   "
102   [(set_attr "predicable" "yes")
103    (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no")
104    (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_reg,load1,load1,store1,store1,r_2_f,f_2_r,fcpys,f_loads,f_stores")
105    (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4")
106    (set_attr "neon_type" "*,*,*,*,*,*,*,*,*,neon_mcr,neon_mrc,neon_vmov,*,*")
107    (set_attr "pool_range"     "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*")
108    (set_attr "neg_pool_range" "*,*,*,*,*,   0,   0,*,*,*,*,*,1008,*")]
112 ;; DImode moves
114 (define_insn "*movdi_vfp"
115   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,q,q,m,w,r,w,w, Uv")
116        (match_operand:DI 1 "di_operand"              "r,rDa,Db,Dc,mi,mi,q,r,w,w,Uvi,w"))]
117   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune != cortexa8
118    && (   register_operand (operands[0], DImode)
119        || register_operand (operands[1], DImode))
120    && !(TARGET_NEON && CONST_INT_P (operands[1])
121         && neon_immediate_valid_for_move (operands[1], DImode, NULL, NULL))"
122   "*
123   switch (which_alternative)
124     {
125     case 0: 
126     case 1:
127     case 2:
128     case 3:
129       return \"#\";
130     case 4:
131     case 5:
132     case 6:
133       return output_move_double (operands, true, NULL);
134     case 7:
135       return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
136     case 8:
137       return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\";
138     case 9:
139       if (TARGET_VFP_SINGLE)
140         return \"fcpys%?\\t%0, %1\\t%@ int\;fcpys%?\\t%p0, %p1\\t%@ int\";
141       else
142         return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
143     case 10: case 11:
144       return output_move_vfp (operands);
145     default:
146       gcc_unreachable ();
147     }
148   "
149   [(set_attr "type" "*,*,*,*,load2,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored")
150    (set_attr "neon_type" "*,*,*,*,*,*,*,neon_mcr_2_mcrr,neon_mrrc,neon_vmov,*,*")
151    (set (attr "length") (cond [(eq_attr "alternative" "1,4,5,6") (const_int 8)
152                               (eq_attr "alternative" "2") (const_int 12)
153                               (eq_attr "alternative" "3") (const_int 16)
154                               (eq_attr "alternative" "9")
155                                (if_then_else
156                                  (match_test "TARGET_VFP_SINGLE")
157                                  (const_int 8)
158                                  (const_int 4))]
159                               (const_int 4)))
160    (set_attr "arm_pool_range"     "*,*,*,*,1020,4096,*,*,*,*,1020,*")
161    (set_attr "thumb2_pool_range"     "*,*,*,*,1018,4094,*,*,*,*,1018,*")
162    (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
163    (set_attr "arch"           "t2,any,any,any,a,t2,any,any,any,any,any,any")]
166 (define_insn "*movdi_vfp_cortexa8"
167   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,r,r,m,w,!r,w,w, Uv")
168        (match_operand:DI 1 "di_operand"              "r,rDa,Db,Dc,mi,mi,r,r,w,w,Uvi,w"))]
169   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune == cortexa8
170     && (   register_operand (operands[0], DImode)
171         || register_operand (operands[1], DImode))
172     && !(TARGET_NEON && CONST_INT_P (operands[1])
173          && neon_immediate_valid_for_move (operands[1], DImode, NULL, NULL))"
174   "*
175   switch (which_alternative)
176     {
177     case 0: 
178     case 1:
179     case 2:
180     case 3:
181       return \"#\";
182     case 4:
183     case 5:
184     case 6:
185       return output_move_double (operands, true, NULL);
186     case 7:
187       return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
188     case 8:
189       return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\";
190     case 9:
191       return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
192     case 10: case 11:
193       return output_move_vfp (operands);
194     default:
195       gcc_unreachable ();
196     }
197   "
198   [(set_attr "type" "*,*,*,*,load2,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored")
199    (set_attr "neon_type" "*,*,*,*,*,*,*,neon_mcr_2_mcrr,neon_mrrc,neon_vmov,*,*")
200    (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8)
201                                (eq_attr "alternative" "2") (const_int 12)
202                                (eq_attr "alternative" "3") (const_int 16)
203                                (eq_attr "alternative" "4,5,6") 
204                                (symbol_ref 
205                                 "arm_count_output_move_double_insns (operands) \
206                                  * 4")]
207                               (const_int 4)))
208    (set_attr "predicable"    "yes")
209    (set_attr "arm_pool_range"     "*,*,*,*,1018,4094,*,*,*,*,1018,*")
210    (set_attr "thumb2_pool_range"     "*,*,*,*,1018,4094,*,*,*,*,1018,*")
211    (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
212    (set (attr "ce_count") 
213         (symbol_ref "get_attr_length (insn) / 4"))
214    (set_attr "arch"           "t2,any,any,any,a,t2,any,any,any,any,any,any")]
217 ;; HFmode moves
218 (define_insn "*movhf_vfp_neon"
219   [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r")
220         (match_operand:HF 1 "general_operand"      " Um, t,m,r,t,r,r,t,F"))]
221   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_NEON_FP16
222    && (   s_register_operand (operands[0], HFmode)
223        || s_register_operand (operands[1], HFmode))"
224   "*
225   switch (which_alternative)
226     {
227     case 0:     /* S register from memory */
228       return \"vld1.16\\t{%z0}, %A1\";
229     case 1:     /* memory from S register */
230       return \"vst1.16\\t{%z1}, %A0\";
231     case 2:     /* ARM register from memory */
232       return \"ldrh\\t%0, %1\\t%@ __fp16\";
233     case 3:     /* memory from ARM register */
234       return \"strh\\t%1, %0\\t%@ __fp16\";
235     case 4:     /* S register from S register */
236       return \"fcpys\\t%0, %1\";
237     case 5:     /* ARM register from ARM register */
238       return \"mov\\t%0, %1\\t%@ __fp16\";
239     case 6:     /* S register from ARM register */
240       return \"fmsr\\t%0, %1\";
241     case 7:     /* ARM register from S register */
242       return \"fmrs\\t%0, %1\";
243     case 8:     /* ARM register from constant */
244       {
245         REAL_VALUE_TYPE r;
246         long bits;
247         rtx ops[4];
249         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
250         bits = real_to_target (NULL, &r, HFmode);
251         ops[0] = operands[0];
252         ops[1] = GEN_INT (bits);
253         ops[2] = GEN_INT (bits & 0xff00);
254         ops[3] = GEN_INT (bits & 0x00ff);
256         if (arm_arch_thumb2)
257           output_asm_insn (\"movw\\t%0, %1\", ops);
258         else
259           output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
260         return \"\";
261        }
262     default:
263       gcc_unreachable ();
264     }
265   "
266   [(set_attr "conds" "unconditional")
267    (set_attr "type" "*,*,load1,store1,fcpys,*,r_2_f,f_2_r,*")
268    (set_attr "neon_type" "neon_vld1_1_2_regs,neon_vst1_1_2_regs_vst2_2_regs,*,*,*,*,*,*,*")
269    (set_attr "length" "4,4,4,4,4,4,4,4,8")]
272 ;; FP16 without element load/store instructions.
273 (define_insn "*movhf_vfp"
274   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
275         (match_operand:HF 1 "general_operand"      " m,r,t,r,r,t,F"))]
276   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16 && !TARGET_NEON_FP16
277    && (   s_register_operand (operands[0], HFmode)
278        || s_register_operand (operands[1], HFmode))"
279   "*
280   switch (which_alternative)
281     {
282     case 0:     /* ARM register from memory */
283       return \"ldrh\\t%0, %1\\t%@ __fp16\";
284     case 1:     /* memory from ARM register */
285       return \"strh\\t%1, %0\\t%@ __fp16\";
286     case 2:     /* S register from S register */
287       return \"fcpys\\t%0, %1\";
288     case 3:     /* ARM register from ARM register */
289       return \"mov\\t%0, %1\\t%@ __fp16\";
290     case 4:     /* S register from ARM register */
291       return \"fmsr\\t%0, %1\";
292     case 5:     /* ARM register from S register */
293       return \"fmrs\\t%0, %1\";
294     case 6:     /* ARM register from constant */
295       {
296         REAL_VALUE_TYPE r;
297         long bits;
298         rtx ops[4];
300         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
301         bits = real_to_target (NULL, &r, HFmode);
302         ops[0] = operands[0];
303         ops[1] = GEN_INT (bits);
304         ops[2] = GEN_INT (bits & 0xff00);
305         ops[3] = GEN_INT (bits & 0x00ff);
307         if (arm_arch_thumb2)
308           output_asm_insn (\"movw\\t%0, %1\", ops);
309         else
310           output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
311         return \"\";
312        }
313     default:
314       gcc_unreachable ();
315     }
316   "
317   [(set_attr "conds" "unconditional")
318    (set_attr "type" "load1,store1,fcpys,*,r_2_f,f_2_r,*")
319    (set_attr "length" "4,4,4,4,4,4,8")]
323 ;; SFmode moves
324 ;; Disparage the w<->r cases because reloading an invalid address is
325 ;; preferable to loading the value via integer registers.
327 (define_insn "*movsf_vfp"
328   [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t  ,Uv,r ,m,t,r")
329         (match_operand:SF 1 "general_operand"      " ?r,t,Dv,UvE,t, mE,r,t,r"))]
330   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
331    && (   s_register_operand (operands[0], SFmode)
332        || s_register_operand (operands[1], SFmode))"
333   "*
334   switch (which_alternative)
335     {
336     case 0:
337       return \"fmsr%?\\t%0, %1\";
338     case 1:
339       return \"fmrs%?\\t%0, %1\";
340     case 2:
341       return \"fconsts%?\\t%0, #%G1\";
342     case 3: case 4:
343       return output_move_vfp (operands);
344     case 5:
345       return \"ldr%?\\t%0, %1\\t%@ float\";
346     case 6:
347       return \"str%?\\t%1, %0\\t%@ float\";
348     case 7:
349       return \"fcpys%?\\t%0, %1\";
350     case 8:
351       return \"mov%?\\t%0, %1\\t%@ float\";
352     default:
353       gcc_unreachable ();
354     }
355   "
356   [(set_attr "predicable" "yes")
357    (set_attr "type"
358      "r_2_f,f_2_r,fconsts,f_loads,f_stores,load1,store1,fcpys,mov_reg")
359    (set_attr "neon_type" "neon_mcr,neon_mrc,*,*,*,*,*,neon_vmov,*")
360    (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
361    (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
364 (define_insn "*thumb2_movsf_vfp"
365   [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t  ,Uv,r ,m,t,r")
366         (match_operand:SF 1 "general_operand"      " ?r,t,Dv,UvE,t, mE,r,t,r"))]
367   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP
368    && (   s_register_operand (operands[0], SFmode)
369        || s_register_operand (operands[1], SFmode))"
370   "*
371   switch (which_alternative)
372     {
373     case 0:
374       return \"fmsr%?\\t%0, %1\";
375     case 1:
376       return \"fmrs%?\\t%0, %1\";
377     case 2:
378       return \"fconsts%?\\t%0, #%G1\";
379     case 3: case 4:
380       return output_move_vfp (operands);
381     case 5:
382       return \"ldr%?\\t%0, %1\\t%@ float\";
383     case 6:
384       return \"str%?\\t%1, %0\\t%@ float\";
385     case 7:
386       return \"fcpys%?\\t%0, %1\";
387     case 8:
388       return \"mov%?\\t%0, %1\\t%@ float\";
389     default:
390       gcc_unreachable ();
391     }
392   "
393   [(set_attr "predicable" "yes")
394    (set_attr "predicable_short_it" "no")
395    (set_attr "type"
396      "r_2_f,f_2_r,fconsts,f_loads,f_stores,load1,store1,fcpys,mov_reg")
397    (set_attr "neon_type" "neon_mcr,neon_mrc,*,*,*,*,*,neon_vmov,*")
398    (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*")
399    (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
402 ;; DFmode moves
404 (define_insn "*movdf_vfp"
405   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w  ,Uv,r, m,w,r")
406         (match_operand:DF 1 "soft_df_operand"              " ?r,w,Dy,UvF,w ,mF,r,w,r"))]
407   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
408    && (   register_operand (operands[0], DFmode)
409        || register_operand (operands[1], DFmode))"
410   "*
411   {
412     switch (which_alternative)
413       {
414       case 0:
415         return \"fmdrr%?\\t%P0, %Q1, %R1\";
416       case 1:
417         return \"fmrrd%?\\t%Q0, %R0, %P1\";
418       case 2:
419         gcc_assert (TARGET_VFP_DOUBLE);
420         return \"fconstd%?\\t%P0, #%G1\";
421       case 3: case 4:
422         return output_move_vfp (operands);
423       case 5: case 6:
424         return output_move_double (operands, true, NULL);
425       case 7:
426         if (TARGET_VFP_SINGLE)
427           return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
428         else
429           return \"fcpyd%?\\t%P0, %P1\";
430       case 8:
431         return \"#\";
432       default:
433         gcc_unreachable ();
434       }
435     }
436   "
437   [(set_attr "type"
438      "r_2_f,f_2_r,fconstd,f_loadd,f_stored,load2,store2,ffarithd,*")
439    (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,*,*,*,*,neon_vmov,*")
440    (set (attr "length") (cond [(eq_attr "alternative" "5,6,8") (const_int 8)
441                                (eq_attr "alternative" "7")
442                                 (if_then_else
443                                  (match_test "TARGET_VFP_SINGLE")
444                                  (const_int 8)
445                                  (const_int 4))]
446                               (const_int 4)))
447    (set_attr "predicable" "yes")
448    (set_attr "pool_range" "*,*,*,1020,*,1020,*,*,*")
449    (set_attr "neg_pool_range" "*,*,*,1004,*,1004,*,*,*")]
452 (define_insn "*thumb2_movdf_vfp"
453   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w  ,Uv,r ,m,w,r")
454         (match_operand:DF 1 "soft_df_operand"              " ?r,w,Dy,UvF,w, mF,r, w,r"))]
455   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP
456    && (   register_operand (operands[0], DFmode)
457        || register_operand (operands[1], DFmode))"
458   "*
459   {
460     switch (which_alternative)
461       {
462       case 0:
463         return \"fmdrr%?\\t%P0, %Q1, %R1\";
464       case 1:
465         return \"fmrrd%?\\t%Q0, %R0, %P1\";
466       case 2:
467         gcc_assert (TARGET_VFP_DOUBLE);
468         return \"fconstd%?\\t%P0, #%G1\";
469       case 3: case 4:
470         return output_move_vfp (operands);
471       case 5: case 6: case 8:
472         return output_move_double (operands, true, NULL);
473       case 7:
474         if (TARGET_VFP_SINGLE)
475           return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
476         else
477           return \"fcpyd%?\\t%P0, %P1\";
478       default:
479         abort ();
480       }
481     }
482   "
483   [(set_attr "type"
484      "r_2_f,f_2_r,fconstd,f_loadd,f_stored,load2,store2,ffarithd,*")
485    (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,*,*,*,*,neon_vmov,*")
486    (set (attr "length") (cond [(eq_attr "alternative" "5,6,8") (const_int 8)
487                                (eq_attr "alternative" "7")
488                                 (if_then_else
489                                  (match_test "TARGET_VFP_SINGLE")
490                                  (const_int 8)
491                                  (const_int 4))]
492                               (const_int 4)))
493    (set_attr "pool_range" "*,*,*,1018,*,4094,*,*,*")
494    (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
498 ;; Conditional move patterns
500 (define_insn "*movsfcc_vfp"
501   [(set (match_operand:SF   0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
502         (if_then_else:SF
503           (match_operator   3 "arm_comparison_operator"
504             [(match_operand 4 "cc_register" "") (const_int 0)])
505           (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
506           (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
507   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
508   "@
509    fcpys%D3\\t%0, %2
510    fcpys%d3\\t%0, %1
511    fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
512    fmsr%D3\\t%0, %2
513    fmsr%d3\\t%0, %1
514    fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
515    fmrs%D3\\t%0, %2
516    fmrs%d3\\t%0, %1
517    fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
518    [(set_attr "conds" "use")
519     (set_attr "length" "4,4,8,4,4,8,4,4,8")
520     (set_attr "type" "fcpys,fcpys,fcpys,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")
521     (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr,neon_mcr,neon_mcr,neon_mrc,neon_mrc,neon_mrc")]
524 (define_insn "*thumb2_movsfcc_vfp"
525   [(set (match_operand:SF   0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
526         (if_then_else:SF
527           (match_operator   3 "arm_comparison_operator"
528             [(match_operand 4 "cc_register" "") (const_int 0)])
529           (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
530           (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
531   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP && !arm_restrict_it"
532   "@
533    it\\t%D3\;fcpys%D3\\t%0, %2
534    it\\t%d3\;fcpys%d3\\t%0, %1
535    ite\\t%D3\;fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
536    it\\t%D3\;fmsr%D3\\t%0, %2
537    it\\t%d3\;fmsr%d3\\t%0, %1
538    ite\\t%D3\;fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
539    it\\t%D3\;fmrs%D3\\t%0, %2
540    it\\t%d3\;fmrs%d3\\t%0, %1
541    ite\\t%D3\;fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
542    [(set_attr "conds" "use")
543     (set_attr "length" "6,6,10,6,6,10,6,6,10")
544     (set_attr "type" "fcpys,fcpys,fcpys,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")
545     (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr,neon_mcr,neon_mcr,neon_mrc,neon_mrc,neon_mrc")]
548 (define_insn "*movdfcc_vfp"
549   [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
550         (if_then_else:DF
551           (match_operator   3 "arm_comparison_operator"
552             [(match_operand 4 "cc_register" "") (const_int 0)])
553           (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
554           (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
555   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
556   "@
557    fcpyd%D3\\t%P0, %P2
558    fcpyd%d3\\t%P0, %P1
559    fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
560    fmdrr%D3\\t%P0, %Q2, %R2
561    fmdrr%d3\\t%P0, %Q1, %R1
562    fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
563    fmrrd%D3\\t%Q0, %R0, %P2
564    fmrrd%d3\\t%Q0, %R0, %P1
565    fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
566    [(set_attr "conds" "use")
567     (set_attr "length" "4,4,8,4,4,8,4,4,8")
568     (set_attr "type" "ffarithd,ffarithd,ffarithd,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")
569     (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mrrc,neon_mrrc,neon_mrrc")]
572 (define_insn "*thumb2_movdfcc_vfp"
573   [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
574         (if_then_else:DF
575           (match_operator   3 "arm_comparison_operator"
576             [(match_operand 4 "cc_register" "") (const_int 0)])
577           (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
578           (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
579   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && !arm_restrict_it"
580   "@
581    it\\t%D3\;fcpyd%D3\\t%P0, %P2
582    it\\t%d3\;fcpyd%d3\\t%P0, %P1
583    ite\\t%D3\;fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
584    it\t%D3\;fmdrr%D3\\t%P0, %Q2, %R2
585    it\t%d3\;fmdrr%d3\\t%P0, %Q1, %R1
586    ite\\t%D3\;fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
587    it\t%D3\;fmrrd%D3\\t%Q0, %R0, %P2
588    it\t%d3\;fmrrd%d3\\t%Q0, %R0, %P1
589    ite\\t%D3\;fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
590    [(set_attr "conds" "use")
591     (set_attr "length" "6,6,10,6,6,10,6,6,10")
592     (set_attr "type" "ffarithd,ffarithd,ffarithd,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")
593     (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mrrc,neon_mrrc,neon_mrrc")]
597 ;; Sign manipulation functions
599 (define_insn "*abssf2_vfp"
600   [(set (match_operand:SF         0 "s_register_operand" "=t")
601         (abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
602   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
603   "fabss%?\\t%0, %1"
604   [(set_attr "predicable" "yes")
605    (set_attr "predicable_short_it" "no")
606    (set_attr "type" "ffariths")]
609 (define_insn "*absdf2_vfp"
610   [(set (match_operand:DF         0 "s_register_operand" "=w")
611         (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
612   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
613   "fabsd%?\\t%P0, %P1"
614   [(set_attr "predicable" "yes")
615    (set_attr "predicable_short_it" "no")
616    (set_attr "type" "ffarithd")]
619 (define_insn "*negsf2_vfp"
620   [(set (match_operand:SF         0 "s_register_operand" "=t,?r")
621         (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))]
622   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
623   "@
624    fnegs%?\\t%0, %1
625    eor%?\\t%0, %1, #-2147483648"
626   [(set_attr "predicable" "yes")
627    (set_attr "predicable_short_it" "no")
628    (set_attr "type" "ffariths")]
631 (define_insn_and_split "*negdf2_vfp"
632   [(set (match_operand:DF         0 "s_register_operand" "=w,?r,?r")
633         (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
634   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
635   "@
636    fnegd%?\\t%P0, %P1
637    #
638    #"
639   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
640    && arm_general_register_operand (operands[0], DFmode)"
641   [(set (match_dup 0) (match_dup 1))]
642   "
643   if (REGNO (operands[0]) == REGNO (operands[1]))
644     {
645       operands[0] = gen_highpart (SImode, operands[0]);
646       operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
647     }
648   else
649     {
650       rtx in_hi, in_lo, out_hi, out_lo;
652       in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
653                            GEN_INT (0x80000000));
654       in_lo = gen_lowpart (SImode, operands[1]);
655       out_hi = gen_highpart (SImode, operands[0]);
656       out_lo = gen_lowpart (SImode, operands[0]);
658       if (REGNO (in_lo) == REGNO (out_hi))
659         {
660           emit_insn (gen_rtx_SET (SImode, out_lo, in_lo));
661           operands[0] = out_hi;
662           operands[1] = in_hi;
663         }
664       else
665         {
666           emit_insn (gen_rtx_SET (SImode, out_hi, in_hi));
667           operands[0] = out_lo;
668           operands[1] = in_lo;
669         }
670     }
671   "
672   [(set_attr "predicable" "yes")
673    (set_attr "predicable_short_it" "no")
674    (set_attr "length" "4,4,8")
675    (set_attr "type" "ffarithd")]
679 ;; Arithmetic insns
681 (define_insn "*addsf3_vfp"
682   [(set (match_operand:SF          0 "s_register_operand" "=t")
683         (plus:SF (match_operand:SF 1 "s_register_operand" "t")
684                  (match_operand:SF 2 "s_register_operand" "t")))]
685   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
686   "fadds%?\\t%0, %1, %2"
687   [(set_attr "predicable" "yes")
688    (set_attr "predicable_short_it" "no")
689    (set_attr "type" "fadds")]
692 (define_insn "*adddf3_vfp"
693   [(set (match_operand:DF          0 "s_register_operand" "=w")
694         (plus:DF (match_operand:DF 1 "s_register_operand" "w")
695                  (match_operand:DF 2 "s_register_operand" "w")))]
696   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
697   "faddd%?\\t%P0, %P1, %P2"
698   [(set_attr "predicable" "yes")
699    (set_attr "predicable_short_it" "no")
700    (set_attr "type" "faddd")]
704 (define_insn "*subsf3_vfp"
705   [(set (match_operand:SF           0 "s_register_operand" "=t")
706         (minus:SF (match_operand:SF 1 "s_register_operand" "t")
707                   (match_operand:SF 2 "s_register_operand" "t")))]
708   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
709   "fsubs%?\\t%0, %1, %2"
710   [(set_attr "predicable" "yes")
711    (set_attr "predicable_short_it" "no")
712    (set_attr "type" "fadds")]
715 (define_insn "*subdf3_vfp"
716   [(set (match_operand:DF           0 "s_register_operand" "=w")
717         (minus:DF (match_operand:DF 1 "s_register_operand" "w")
718                   (match_operand:DF 2 "s_register_operand" "w")))]
719   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
720   "fsubd%?\\t%P0, %P1, %P2"
721   [(set_attr "predicable" "yes")
722    (set_attr "predicable_short_it" "no")
723    (set_attr "type" "faddd")]
727 ;; Division insns
729 (define_insn "*divsf3_vfp"
730   [(set (match_operand:SF         0 "s_register_operand" "=t")
731         (div:SF (match_operand:SF 1 "s_register_operand" "t")
732                 (match_operand:SF 2 "s_register_operand" "t")))]
733   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
734   "fdivs%?\\t%0, %1, %2"
735   [(set_attr "predicable" "yes")
736    (set_attr "predicable_short_it" "no")
737    (set_attr "type" "fdivs")]
740 (define_insn "*divdf3_vfp"
741   [(set (match_operand:DF         0 "s_register_operand" "=w")
742         (div:DF (match_operand:DF 1 "s_register_operand" "w")
743                 (match_operand:DF 2 "s_register_operand" "w")))]
744   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
745   "fdivd%?\\t%P0, %P1, %P2"
746   [(set_attr "predicable" "yes")
747    (set_attr "predicable_short_it" "no")
748    (set_attr "type" "fdivd")]
752 ;; Multiplication insns
754 (define_insn "*mulsf3_vfp"
755   [(set (match_operand:SF          0 "s_register_operand" "=t")
756         (mult:SF (match_operand:SF 1 "s_register_operand" "t")
757                  (match_operand:SF 2 "s_register_operand" "t")))]
758   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
759   "fmuls%?\\t%0, %1, %2"
760   [(set_attr "predicable" "yes")
761    (set_attr "predicable_short_it" "no")
762    (set_attr "type" "fmuls")]
765 (define_insn "*muldf3_vfp"
766   [(set (match_operand:DF          0 "s_register_operand" "=w")
767         (mult:DF (match_operand:DF 1 "s_register_operand" "w")
768                  (match_operand:DF 2 "s_register_operand" "w")))]
769   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
770   "fmuld%?\\t%P0, %P1, %P2"
771   [(set_attr "predicable" "yes")
772    (set_attr "predicable_short_it" "no")
773    (set_attr "type" "fmuld")]
776 (define_insn "*mulsf3negsf_vfp"
777   [(set (match_operand:SF                  0 "s_register_operand" "=t")
778         (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
779                  (match_operand:SF         2 "s_register_operand" "t")))]
780   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
781   "fnmuls%?\\t%0, %1, %2"
782   [(set_attr "predicable" "yes")
783    (set_attr "predicable_short_it" "no")
784    (set_attr "type" "fmuls")]
787 (define_insn "*muldf3negdf_vfp"
788   [(set (match_operand:DF                  0 "s_register_operand" "=w")
789         (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
790                  (match_operand:DF         2 "s_register_operand" "w")))]
791   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
792   "fnmuld%?\\t%P0, %P1, %P2"
793   [(set_attr "predicable" "yes")
794    (set_attr "predicable_short_it" "no")
795    (set_attr "type" "fmuld")]
799 ;; Multiply-accumulate insns
801 ;; 0 = 1 * 2 + 0
802 (define_insn "*mulsf3addsf_vfp"
803   [(set (match_operand:SF                   0 "s_register_operand" "=t")
804         (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
805                           (match_operand:SF 3 "s_register_operand" "t"))
806                  (match_operand:SF          1 "s_register_operand" "0")))]
807   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
808   "fmacs%?\\t%0, %2, %3"
809   [(set_attr "predicable" "yes")
810    (set_attr "predicable_short_it" "no")
811    (set_attr "type" "fmacs")]
814 (define_insn "*muldf3adddf_vfp"
815   [(set (match_operand:DF                   0 "s_register_operand" "=w")
816         (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
817                           (match_operand:DF 3 "s_register_operand" "w"))
818                  (match_operand:DF          1 "s_register_operand" "0")))]
819   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
820   "fmacd%?\\t%P0, %P2, %P3"
821   [(set_attr "predicable" "yes")
822    (set_attr "predicable_short_it" "no")
823    (set_attr "type" "fmacd")]
826 ;; 0 = 1 * 2 - 0
827 (define_insn "*mulsf3subsf_vfp"
828   [(set (match_operand:SF                    0 "s_register_operand" "=t")
829         (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
830                            (match_operand:SF 3 "s_register_operand" "t"))
831                   (match_operand:SF          1 "s_register_operand" "0")))]
832   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
833   "fmscs%?\\t%0, %2, %3"
834   [(set_attr "predicable" "yes")
835    (set_attr "predicable_short_it" "no")
836    (set_attr "type" "fmacs")]
839 (define_insn "*muldf3subdf_vfp"
840   [(set (match_operand:DF                    0 "s_register_operand" "=w")
841         (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
842                            (match_operand:DF 3 "s_register_operand" "w"))
843                   (match_operand:DF          1 "s_register_operand" "0")))]
844   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
845   "fmscd%?\\t%P0, %P2, %P3"
846   [(set_attr "predicable" "yes")
847    (set_attr "predicable_short_it" "no")
848    (set_attr "type" "fmacd")]
851 ;; 0 = -(1 * 2) + 0
852 (define_insn "*mulsf3negsfaddsf_vfp"
853   [(set (match_operand:SF                    0 "s_register_operand" "=t")
854         (minus:SF (match_operand:SF          1 "s_register_operand" "0")
855                   (mult:SF (match_operand:SF 2 "s_register_operand" "t")
856                            (match_operand:SF 3 "s_register_operand" "t"))))]
857   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
858   "fnmacs%?\\t%0, %2, %3"
859   [(set_attr "predicable" "yes")
860    (set_attr "predicable_short_it" "no")
861    (set_attr "type" "fmacs")]
864 (define_insn "*fmuldf3negdfadddf_vfp"
865   [(set (match_operand:DF                    0 "s_register_operand" "=w")
866         (minus:DF (match_operand:DF          1 "s_register_operand" "0")
867                   (mult:DF (match_operand:DF 2 "s_register_operand" "w")
868                            (match_operand:DF 3 "s_register_operand" "w"))))]
869   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
870   "fnmacd%?\\t%P0, %P2, %P3"
871   [(set_attr "predicable" "yes")
872    (set_attr "predicable_short_it" "no")
873    (set_attr "type" "fmacd")]
877 ;; 0 = -(1 * 2) - 0
878 (define_insn "*mulsf3negsfsubsf_vfp"
879   [(set (match_operand:SF                     0 "s_register_operand" "=t")
880         (minus:SF (mult:SF
881                     (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
882                     (match_operand:SF         3 "s_register_operand" "t"))
883                   (match_operand:SF           1 "s_register_operand" "0")))]
884   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
885   "fnmscs%?\\t%0, %2, %3"
886   [(set_attr "predicable" "yes")
887    (set_attr "predicable_short_it" "no")
888    (set_attr "type" "fmacs")]
891 (define_insn "*muldf3negdfsubdf_vfp"
892   [(set (match_operand:DF                     0 "s_register_operand" "=w")
893         (minus:DF (mult:DF
894                     (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
895                     (match_operand:DF         3 "s_register_operand" "w"))
896                   (match_operand:DF           1 "s_register_operand" "0")))]
897   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
898   "fnmscd%?\\t%P0, %P2, %P3"
899   [(set_attr "predicable" "yes")
900    (set_attr "predicable_short_it" "no")
901    (set_attr "type" "fmacd")]
904 ;; Fused-multiply-accumulate
906 (define_insn "fma<SDF:mode>4"
907   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
908         (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
909                  (match_operand:SDF 2 "register_operand" "<F_constraint>")
910                  (match_operand:SDF 3 "register_operand" "0")))]
911   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
912   "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
913   [(set_attr "predicable" "yes")
914    (set_attr "predicable_short_it" "no")
915    (set_attr "type" "ffma<vfp_type>")]
918 (define_insn "*fmsub<SDF:mode>4"
919   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
920         (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
921                                              "<F_constraint>"))
922                  (match_operand:SDF 2 "register_operand" "<F_constraint>")
923                  (match_operand:SDF 3 "register_operand" "0")))]
924   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
925   "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
926   [(set_attr "predicable" "yes")
927    (set_attr "predicable_short_it" "no")
928    (set_attr "type" "ffma<vfp_type>")]
931 (define_insn "*fnmsub<SDF:mode>4"
932   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
933         (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
934                  (match_operand:SDF 2 "register_operand" "<F_constraint>")
935                  (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
936   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
937   "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
938   [(set_attr "predicable" "yes")
939    (set_attr "predicable_short_it" "no")
940    (set_attr "type" "ffma<vfp_type>")]
943 (define_insn "*fnmadd<SDF:mode>4"
944   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
945         (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
946                                                "<F_constraint>"))
947                  (match_operand:SDF 2 "register_operand" "<F_constraint>")
948                  (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
949   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
950   "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
951   [(set_attr "predicable" "yes")
952    (set_attr "predicable_short_it" "no")
953    (set_attr "type" "ffma<vfp_type>")]
957 ;; Conversion routines
959 (define_insn "*extendsfdf2_vfp"
960   [(set (match_operand:DF                  0 "s_register_operand" "=w")
961         (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
962   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
963   "fcvtds%?\\t%P0, %1"
964   [(set_attr "predicable" "yes")
965    (set_attr "predicable_short_it" "no")
966    (set_attr "type" "f_cvt")]
969 (define_insn "*truncdfsf2_vfp"
970   [(set (match_operand:SF                  0 "s_register_operand" "=t")
971         (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
972   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
973   "fcvtsd%?\\t%0, %P1"
974   [(set_attr "predicable" "yes")
975    (set_attr "predicable_short_it" "no")
976    (set_attr "type" "f_cvt")]
979 (define_insn "extendhfsf2"
980   [(set (match_operand:SF                  0 "s_register_operand" "=t")
981         (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))]
982   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16"
983   "vcvtb%?.f32.f16\\t%0, %1"
984   [(set_attr "predicable" "yes")
985    (set_attr "predicable_short_it" "no")
986    (set_attr "type" "f_cvt")]
989 (define_insn "truncsfhf2"
990   [(set (match_operand:HF                  0 "s_register_operand" "=t")
991         (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
992   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16"
993   "vcvtb%?.f16.f32\\t%0, %1"
994   [(set_attr "predicable" "yes")
995    (set_attr "predicable_short_it" "no")
996    (set_attr "type" "f_cvt")]
999 (define_insn "*truncsisf2_vfp"
1000   [(set (match_operand:SI                 0 "s_register_operand" "=t")
1001         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1002   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1003   "ftosizs%?\\t%0, %1"
1004   [(set_attr "predicable" "yes")
1005    (set_attr "predicable_short_it" "no")
1006    (set_attr "type" "f_cvt")]
1009 (define_insn "*truncsidf2_vfp"
1010   [(set (match_operand:SI                 0 "s_register_operand" "=t")
1011         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
1012   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1013   "ftosizd%?\\t%0, %P1"
1014   [(set_attr "predicable" "yes")
1015    (set_attr "predicable_short_it" "no")
1016    (set_attr "type" "f_cvt")]
1020 (define_insn "fixuns_truncsfsi2"
1021   [(set (match_operand:SI                 0 "s_register_operand" "=t")
1022         (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1023   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1024   "ftouizs%?\\t%0, %1"
1025   [(set_attr "predicable" "yes")
1026    (set_attr "predicable_short_it" "no")
1027    (set_attr "type" "f_cvt")]
1030 (define_insn "fixuns_truncdfsi2"
1031   [(set (match_operand:SI                 0 "s_register_operand" "=t")
1032         (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
1033   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1034   "ftouizd%?\\t%0, %P1"
1035   [(set_attr "predicable" "yes")
1036    (set_attr "predicable_short_it" "no")
1037    (set_attr "type" "f_cvt")]
1041 (define_insn "*floatsisf2_vfp"
1042   [(set (match_operand:SF           0 "s_register_operand" "=t")
1043         (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1044   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1045   "fsitos%?\\t%0, %1"
1046   [(set_attr "predicable" "yes")
1047    (set_attr "predicable_short_it" "no")
1048    (set_attr "type" "f_cvt")]
1051 (define_insn "*floatsidf2_vfp"
1052   [(set (match_operand:DF           0 "s_register_operand" "=w")
1053         (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1054   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1055   "fsitod%?\\t%P0, %1"
1056   [(set_attr "predicable" "yes")
1057    (set_attr "predicable_short_it" "no")
1058    (set_attr "type" "f_cvt")]
1062 (define_insn "floatunssisf2"
1063   [(set (match_operand:SF           0 "s_register_operand" "=t")
1064         (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1065   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1066   "fuitos%?\\t%0, %1"
1067   [(set_attr "predicable" "yes")
1068    (set_attr "predicable_short_it" "no")
1069    (set_attr "type" "f_cvt")]
1072 (define_insn "floatunssidf2"
1073   [(set (match_operand:DF           0 "s_register_operand" "=w")
1074         (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1075   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1076   "fuitod%?\\t%P0, %1"
1077   [(set_attr "predicable" "yes")
1078    (set_attr "predicable_short_it" "no")
1079    (set_attr "type" "f_cvt")]
1083 ;; Sqrt insns.
1085 (define_insn "*sqrtsf2_vfp"
1086   [(set (match_operand:SF          0 "s_register_operand" "=t")
1087         (sqrt:SF (match_operand:SF 1 "s_register_operand" "t")))]
1088   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1089   "fsqrts%?\\t%0, %1"
1090   [(set_attr "predicable" "yes")
1091    (set_attr "predicable_short_it" "no")
1092    (set_attr "type" "fdivs")]
1095 (define_insn "*sqrtdf2_vfp"
1096   [(set (match_operand:DF          0 "s_register_operand" "=w")
1097         (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
1098   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1099   "fsqrtd%?\\t%P0, %P1"
1100   [(set_attr "predicable" "yes")
1101    (set_attr "predicable_short_it" "no")
1102    (set_attr "type" "fdivd")]
1106 ;; Patterns to split/copy vfp condition flags.
1108 (define_insn "*movcc_vfp"
1109   [(set (reg CC_REGNUM)
1110         (reg VFPCC_REGNUM))]
1111   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1112   "fmstat%?"
1113   [(set_attr "conds" "set")
1114    (set_attr "type" "f_flag")]
1117 (define_insn_and_split "*cmpsf_split_vfp"
1118   [(set (reg:CCFP CC_REGNUM)
1119         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "t")
1120                       (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1121   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1122   "#"
1123   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1124   [(set (reg:CCFP VFPCC_REGNUM)
1125         (compare:CCFP (match_dup 0)
1126                       (match_dup 1)))
1127    (set (reg:CCFP CC_REGNUM)
1128         (reg:CCFP VFPCC_REGNUM))]
1129   ""
1132 (define_insn_and_split "*cmpsf_trap_split_vfp"
1133   [(set (reg:CCFPE CC_REGNUM)
1134         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "t")
1135                        (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1136   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1137   "#"
1138   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1139   [(set (reg:CCFPE VFPCC_REGNUM)
1140         (compare:CCFPE (match_dup 0)
1141                        (match_dup 1)))
1142    (set (reg:CCFPE CC_REGNUM)
1143         (reg:CCFPE VFPCC_REGNUM))]
1144   ""
1147 (define_insn_and_split "*cmpdf_split_vfp"
1148   [(set (reg:CCFP CC_REGNUM)
1149         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w")
1150                       (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1151   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1152   "#"
1153   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1154   [(set (reg:CCFP VFPCC_REGNUM)
1155         (compare:CCFP (match_dup 0)
1156                        (match_dup 1)))
1157    (set (reg:CCFP CC_REGNUM)
1158         (reg:CCFP VFPCC_REGNUM))]
1159   ""
1162 (define_insn_and_split "*cmpdf_trap_split_vfp"
1163   [(set (reg:CCFPE CC_REGNUM)
1164         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w")
1165                        (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1166   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1167   "#"
1168   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1169   [(set (reg:CCFPE VFPCC_REGNUM)
1170         (compare:CCFPE (match_dup 0)
1171                        (match_dup 1)))
1172    (set (reg:CCFPE CC_REGNUM)
1173         (reg:CCFPE VFPCC_REGNUM))]
1174   ""
1178 ;; Comparison patterns
1180 (define_insn "*cmpsf_vfp"
1181   [(set (reg:CCFP VFPCC_REGNUM)
1182         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "t,t")
1183                       (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1184   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1185   "@
1186    fcmps%?\\t%0, %1
1187    fcmpzs%?\\t%0"
1188   [(set_attr "predicable" "yes")
1189    (set_attr "predicable_short_it" "no")
1190    (set_attr "type" "fcmps")]
1193 (define_insn "*cmpsf_trap_vfp"
1194   [(set (reg:CCFPE VFPCC_REGNUM)
1195         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "t,t")
1196                        (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1197   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1198   "@
1199    fcmpes%?\\t%0, %1
1200    fcmpezs%?\\t%0"
1201   [(set_attr "predicable" "yes")
1202    (set_attr "predicable_short_it" "no")
1203    (set_attr "type" "fcmps")]
1206 (define_insn "*cmpdf_vfp"
1207   [(set (reg:CCFP VFPCC_REGNUM)
1208         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w,w")
1209                       (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1210   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1211   "@
1212    fcmpd%?\\t%P0, %P1
1213    fcmpzd%?\\t%P0"
1214   [(set_attr "predicable" "yes")
1215    (set_attr "predicable_short_it" "no")
1216    (set_attr "type" "fcmpd")]
1219 (define_insn "*cmpdf_trap_vfp"
1220   [(set (reg:CCFPE VFPCC_REGNUM)
1221         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w,w")
1222                        (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1223   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1224   "@
1225    fcmped%?\\t%P0, %P1
1226    fcmpezd%?\\t%P0"
1227   [(set_attr "predicable" "yes")
1228    (set_attr "predicable_short_it" "no")
1229    (set_attr "type" "fcmpd")]
1232 ;; Fixed point to floating point conversions. 
1233 (define_code_iterator FCVT [unsigned_float float])
1234 (define_code_attr FCVTI32typename [(unsigned_float "u32") (float "s32")])
1236 (define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1237   [(set (match_operand:SF 0 "s_register_operand" "=t")
1238         (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
1239                  (match_operand 2 
1240                         "const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1241   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1242   "vcvt.f32.<FCVTI32typename>\\t%0, %1, %v2"
1243  [(set_attr "predicable" "no")
1244   (set_attr "type" "f_cvt")]
1247 ;; Not the ideal way of implementing this. Ideally we would be able to split
1248 ;; this into a move to a DP register and then a vcvt.f64.i32
1249 (define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1250   [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1251         (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
1252                  (match_operand 2 
1253                      "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
1254   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math 
1255   && !TARGET_VFP_SINGLE"
1256   "@
1257   vmov.f32\\t%0, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1258   vmov.f32\\t%0, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1259   vmov.f64\\t%P0, %1, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1260  [(set_attr "predicable" "no")
1261   (set_attr "type" "f_cvt")
1262   (set_attr "length" "8")]
1265 ;; Store multiple insn used in function prologue.
1266 (define_insn "*push_multi_vfp"
1267   [(match_parallel 2 "multi_register_push"
1268     [(set (match_operand:BLK 0 "memory_operand" "=m")
1269           (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
1270                       UNSPEC_PUSH_MULT))])]
1271   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1272   "* return vfp_output_fstmd (operands);"
1273   [(set_attr "type" "f_stored")]
1276 ;; VRINT round to integral instructions.
1277 ;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
1278 ;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
1279 ;; rintsf2, rintdf2.
1280 (define_insn "<vrint_pattern><SDF:mode>2"
1281   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1282         (unspec:SDF [(match_operand:SDF 1
1283                          "register_operand" "<F_constraint>")]
1284          VRINT))]
1285   "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
1286   "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
1287   [(set_attr "predicable" "<vrint_predicable>")
1288    (set_attr "predicable_short_it" "no")
1289    (set_attr "type" "f_rint<vfp_type>")]
1292 ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
1293 ;; The 'smax' and 'smin' RTL standard pattern names do not specify which
1294 ;; operand will be returned when both operands are zero (i.e. they may not
1295 ;; honour signed zeroes), or when either operand is NaN.  Therefore GCC
1296 ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
1297 ;; NaNs.
1299 (define_insn "smax<mode>3"
1300   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1301         (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1302                   (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1303   "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
1304   "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1305   [(set_attr "type" "f_minmax<vfp_type>")]
1308 (define_insn "smin<mode>3"
1309   [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1310         (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1311                   (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1312   "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
1313   "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1314   [(set_attr "type" "f_minmax<vfp_type>")]
1317 ;; Unimplemented insns:
1318 ;; fldm*
1319 ;; fstm*
1320 ;; fmdhr et al (VFPv1)
1321 ;; Support for xD (single precision only) variants.
1322 ;; fmrrs, fmsrr