Merge from mainline
[official-gcc.git] / gcc / config / arm / vfp.md
blobc85f58cf88b2740af60339576e263f5d942ba515
1 ;; ARM VFP coprocessor Machine Description
2 ;; Copyright (C) 2003, 2005 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery, LLC.
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 2, 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 COPYING.  If not, write to the Free
19 ;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20 ;; 02110-1301, USA.  */
22 ;; Additional register numbers
23 (define_constants
24   [(VFPCC_REGNUM 95)]
27 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28 ;; Pipeline description
29 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31 (define_automaton "vfp11")
33 ;; There are 3 pipelines in the VFP11 unit.
35 ;; - A 8-stage FMAC pipeline (7 execute + writeback) with forward from
36 ;;   fourth stage for simple operations.
38 ;; - A 5-stage DS pipeline (4 execute + writeback) for divide/sqrt insns.
39 ;;   These insns also uses first execute stage of FMAC pipeline.
41 ;; - A 4-stage LS pipeline (execute + 2 memory + writeback) with forward from
42 ;;   second memory stage for loads.
44 ;; We do not model Write-After-Read hazards.
45 ;; We do not do write scheduling with the arm core, so it is only necessary
46 ;; to model the first stage of each pipeline
47 ;; ??? Need to model LS pipeline properly for load/store multiple?
48 ;; We do not model fmstat properly.  This could be done by modeling pipelines
49 ;; properly and defining an absence set between a dummy fmstat unit and all
50 ;; other vfp units.
52 (define_cpu_unit "fmac" "vfp11")
54 (define_cpu_unit "ds" "vfp11")
56 (define_cpu_unit "vfp_ls" "vfp11")
58 (define_cpu_unit "fmstat" "vfp11")
60 (exclusion_set "fmac,ds" "fmstat")
62 ;; The VFP "type" attributes differ from those used in the FPA model.
63 ;; ffarith      Fast floating point insns, e.g. abs, neg, cpy, cmp.
64 ;; farith       Most arithmetic insns.
65 ;; fmul         Double precision multiply.
66 ;; fdivs        Single precision sqrt or division.
67 ;; fdivd        Double precision sqrt or division.
68 ;; f_flag       fmstat operation
69 ;; f_load[sd]   Floating point load from memory.
70 ;; f_store[sd]  Floating point store to memory.
71 ;; f_2_r        Transfer vfp to arm reg.
72 ;; r_2_f        Transfer arm to vfp reg.
73 ;; f_cvt        Convert floating<->integral
75 (define_insn_reservation "vfp_ffarith" 4
76  (and (eq_attr "generic_vfp" "yes")
77       (eq_attr "type" "ffarith"))
78  "fmac")
80 (define_insn_reservation "vfp_farith" 8
81  (and (eq_attr "generic_vfp" "yes")
82       (eq_attr "type" "farith,f_cvt"))
83  "fmac")
85 (define_insn_reservation "vfp_fmul" 9
86  (and (eq_attr "generic_vfp" "yes")
87       (eq_attr "type" "fmul"))
88  "fmac*2")
90 (define_insn_reservation "vfp_fdivs" 19
91  (and (eq_attr "generic_vfp" "yes")
92       (eq_attr "type" "fdivs"))
93  "ds*15")
95 (define_insn_reservation "vfp_fdivd" 33
96  (and (eq_attr "generic_vfp" "yes")
97       (eq_attr "type" "fdivd"))
98  "fmac+ds*29")
100 ;; Moves to/from arm regs also use the load/store pipeline.
101 (define_insn_reservation "vfp_fload" 4
102  (and (eq_attr "generic_vfp" "yes")
103       (eq_attr "type" "f_loads,f_loadd,r_2_f"))
104  "vfp_ls")
106 (define_insn_reservation "vfp_fstore" 4
107  (and (eq_attr "generic_vfp" "yes")
108       (eq_attr "type" "f_stores,f_stored,f_2_r"))
109  "vfp_ls")
111 (define_insn_reservation "vfp_to_cpsr" 4
112  (and (eq_attr "generic_vfp" "yes")
113       (eq_attr "type" "f_flag"))
114  "fmstat,vfp_ls*3")
116 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
117 ;; Insn pattern
118 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
120 ;; SImode moves
121 ;; ??? For now do not allow loading constants into vfp regs.  This causes
122 ;; problems because small constants get converted into adds.
123 (define_insn "*arm_movsi_vfp"
124   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r ,m,*w,r,*w,*w, *Uv")
125       (match_operand:SI 1 "general_operand"        "rI,K,mi,r,r,*w,*w,*Uvi,*w"))]
126   "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
127    && (   s_register_operand (operands[0], SImode)
128        || s_register_operand (operands[1], SImode))"
129   "@
130   mov%?\\t%0, %1
131   mvn%?\\t%0, #%B1
132   ldr%?\\t%0, %1
133   str%?\\t%1, %0
134   fmsr%?\\t%0, %1\\t%@ int
135   fmrs%?\\t%0, %1\\t%@ int
136   fcpys%?\\t%0, %1\\t%@ int
137   flds%?\\t%0, %1\\t%@ int
138   fsts%?\\t%1, %0\\t%@ int"
139   [(set_attr "predicable" "yes")
140    (set_attr "type" "*,*,load1,store1,r_2_f,f_2_r,ffarith,f_loads,f_stores")
141    (set_attr "pool_range"     "*,*,4096,*,*,*,*,1020,*")
142    (set_attr "neg_pool_range" "*,*,4084,*,*,*,*,1008,*")]
146 ;; DImode moves
148 (define_insn "*arm_movdi_vfp"
149   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,m,w,r,w,w, Uv")
150         (match_operand:DI 1 "di_operand"              "rIK,mi,r,r,w,w,Uvi,w"))]
151   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
152    && (   register_operand (operands[0], DImode)
153        || register_operand (operands[1], DImode))"
154   "*
155   switch (which_alternative)
156     {
157     case 0: 
158       return \"#\";
159     case 1:
160     case 2:
161       return output_move_double (operands);
162     case 3:
163       return \"fmdrr%?\\t%P0, %1\\t%@ int\";
164     case 4:
165       return \"fmrrd%?\\t%0, %1\\t%@ int\";
166     case 5:
167       return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
168     case 6:
169       return \"fldd%?\\t%P0, %1\\t%@ int\";
170     case 7:
171       return \"fstd%?\\t%P1, %0\\t%@ int\";
172     default:
173       gcc_unreachable ();
174     }
175   "
176   [(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarith,f_loadd,f_stored")
177    (set_attr "length" "8,8,8,4,4,4,4,4")
178    (set_attr "pool_range"     "*,1020,*,*,*,*,1020,*")
179    (set_attr "neg_pool_range" "*,1008,*,*,*,*,1008,*")]
183 ;; SFmode moves
185 (define_insn "*movsf_vfp"
186   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,r,w  ,Uv,r ,m,w,r")
187         (match_operand:SF 1 "general_operand"      " r,w,UvE,w, mE,r,w,r"))]
188   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
189    && (   s_register_operand (operands[0], SFmode)
190        || s_register_operand (operands[1], SFmode))"
191   "@
192   fmsr%?\\t%0, %1
193   fmrs%?\\t%0, %1
194   flds%?\\t%0, %1
195   fsts%?\\t%1, %0
196   ldr%?\\t%0, %1\\t%@ float
197   str%?\\t%1, %0\\t%@ float
198   fcpys%?\\t%0, %1
199   mov%?\\t%0, %1\\t%@ float"
200   [(set_attr "predicable" "yes")
201    (set_attr "type" "r_2_f,f_2_r,ffarith,*,f_loads,f_stores,load1,store1")
202    (set_attr "pool_range" "*,*,1020,*,4096,*,*,*")
203    (set_attr "neg_pool_range" "*,*,1008,*,4080,*,*,*")]
207 ;; DFmode moves
209 (define_insn "*movdf_vfp"
210   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,r,r, m,w  ,Uv,w,r")
211         (match_operand:DF 1 "soft_df_operand"              " r,w,mF,r,UvF,w, w,r"))]
212   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
213    && (   register_operand (operands[0], DFmode)
214        || register_operand (operands[1], DFmode))"
215   "*
216   {
217     switch (which_alternative)
218       {
219       case 0:
220         return \"fmdrr%?\\t%P0, %Q1, %R1\";
221       case 1:
222         return \"fmrrd%?\\t%Q0, %R0, %P1\";
223       case 2: case 3:
224         return output_move_double (operands);
225       case 4:
226         return \"fldd%?\\t%P0, %1\";
227       case 5:
228         return \"fstd%?\\t%P1, %0\";
229       case 6:
230         return \"fcpyd%?\\t%P0, %P1\";
231       case 7:
232         return \"#\";
233       default:
234         gcc_unreachable ();
235       }
236     }
237   "
238   [(set_attr "type" "r_2_f,f_2_r,ffarith,*,load2,store2,f_loadd,f_stored")
239    (set_attr "length" "4,4,8,8,4,4,4,8")
240    (set_attr "pool_range" "*,*,1020,*,1020,*,*,*")
241    (set_attr "neg_pool_range" "*,*,1008,*,1008,*,*,*")]
245 ;; Conditional move patterns
247 (define_insn "*movsfcc_vfp"
248   [(set (match_operand:SF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
249         (if_then_else:SF
250           (match_operator   3 "arm_comparison_operator"
251             [(match_operand 4 "cc_register" "") (const_int 0)])
252           (match_operand:SF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
253           (match_operand:SF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
254   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
255   "@
256    fcpys%D3\\t%0, %2
257    fcpys%d3\\t%0, %1
258    fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
259    fmsr%D3\\t%0, %2
260    fmsr%d3\\t%0, %1
261    fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
262    fmrs%D3\\t%0, %2
263    fmrs%d3\\t%0, %1
264    fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
265    [(set_attr "conds" "use")
266     (set_attr "length" "4,4,8,4,4,8,4,4,8")
267     (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
270 (define_insn "*movdfcc_vfp"
271   [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
272         (if_then_else:DF
273           (match_operator   3 "arm_comparison_operator"
274             [(match_operand 4 "cc_register" "") (const_int 0)])
275           (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
276           (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
277   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
278   "@
279    fcpyd%D3\\t%P0, %P2
280    fcpyd%d3\\t%P0, %P1
281    fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
282    fmdrr%D3\\t%P0, %Q2, %R2
283    fmdrr%d3\\t%P0, %Q1, %R1
284    fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
285    fmrrd%D3\\t%Q0, %R0, %P2
286    fmrrd%d3\\t%Q0, %R0, %P1
287    fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
288    [(set_attr "conds" "use")
289     (set_attr "length" "4,4,8,4,4,8,4,4,8")
290     (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
294 ;; Sign manipulation functions
296 (define_insn "*abssf2_vfp"
297   [(set (match_operand:SF         0 "s_register_operand" "=w")
298         (abs:SF (match_operand:SF 1 "s_register_operand" "w")))]
299   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
300   "fabss%?\\t%0, %1"
301   [(set_attr "predicable" "yes")
302    (set_attr "type" "ffarith")]
305 (define_insn "*absdf2_vfp"
306   [(set (match_operand:DF         0 "s_register_operand" "=w")
307         (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
308   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
309   "fabsd%?\\t%P0, %P1"
310   [(set_attr "predicable" "yes")
311    (set_attr "type" "ffarith")]
314 (define_insn "*negsf2_vfp"
315   [(set (match_operand:SF         0 "s_register_operand" "=w,?r")
316         (neg:SF (match_operand:SF 1 "s_register_operand" "w,r")))]
317   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
318   "@
319    fnegs%?\\t%0, %1
320    eor%?\\t%0, %1, #-2147483648"
321   [(set_attr "predicable" "yes")
322    (set_attr "type" "ffarith")]
325 (define_insn_and_split "*negdf2_vfp"
326   [(set (match_operand:DF         0 "s_register_operand" "=w,?r,?r")
327         (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
328   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
329   "@
330    fnegd%?\\t%P0, %P1
331    #
332    #"
333   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && reload_completed
334    && arm_general_register_operand (operands[0], DFmode)"
335   [(set (match_dup 0) (match_dup 1))]
336   "
337   if (REGNO (operands[0]) == REGNO (operands[1]))
338     {
339       operands[0] = gen_highpart (SImode, operands[0]);
340       operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
341     }
342   else
343     {
344       rtx in_hi, in_lo, out_hi, out_lo;
346       in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
347                            GEN_INT (0x80000000));
348       in_lo = gen_lowpart (SImode, operands[1]);
349       out_hi = gen_highpart (SImode, operands[0]);
350       out_lo = gen_lowpart (SImode, operands[0]);
352       if (REGNO (in_lo) == REGNO (out_hi))
353         {
354           emit_insn (gen_rtx_SET (SImode, out_lo, in_lo));
355           operands[0] = out_hi;
356           operands[1] = in_hi;
357         }
358       else
359         {
360           emit_insn (gen_rtx_SET (SImode, out_hi, in_hi));
361           operands[0] = out_lo;
362           operands[1] = in_lo;
363         }
364     }
365   "
366   [(set_attr "predicable" "yes")
367    (set_attr "length" "4,4,8")
368    (set_attr "type" "ffarith")]
372 ;; Arithmetic insns
374 (define_insn "*addsf3_vfp"
375   [(set (match_operand:SF          0 "s_register_operand" "=w")
376         (plus:SF (match_operand:SF 1 "s_register_operand" "w")
377                  (match_operand:SF 2 "s_register_operand" "w")))]
378   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
379   "fadds%?\\t%0, %1, %2"
380   [(set_attr "predicable" "yes")
381    (set_attr "type" "farith")]
384 (define_insn "*adddf3_vfp"
385   [(set (match_operand:DF          0 "s_register_operand" "=w")
386         (plus:DF (match_operand:DF 1 "s_register_operand" "w")
387                  (match_operand:DF 2 "s_register_operand" "w")))]
388   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
389   "faddd%?\\t%P0, %P1, %P2"
390   [(set_attr "predicable" "yes")
391    (set_attr "type" "farith")]
395 (define_insn "*subsf3_vfp"
396   [(set (match_operand:SF           0 "s_register_operand" "=w")
397         (minus:SF (match_operand:SF 1 "s_register_operand" "w")
398                   (match_operand:SF 2 "s_register_operand" "w")))]
399   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
400   "fsubs%?\\t%0, %1, %2"
401   [(set_attr "predicable" "yes")
402    (set_attr "type" "farith")]
405 (define_insn "*subdf3_vfp"
406   [(set (match_operand:DF           0 "s_register_operand" "=w")
407         (minus:DF (match_operand:DF 1 "s_register_operand" "w")
408                   (match_operand:DF 2 "s_register_operand" "w")))]
409   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
410   "fsubd%?\\t%P0, %P1, %P2"
411   [(set_attr "predicable" "yes")
412    (set_attr "type" "farith")]
416 ;; Division insns
418 (define_insn "*divsf3_vfp"
419   [(set (match_operand:SF         0 "s_register_operand" "+w")
420         (div:SF (match_operand:SF 1 "s_register_operand" "w")
421                 (match_operand:SF 2 "s_register_operand" "w")))]
422   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
423   "fdivs%?\\t%0, %1, %2"
424   [(set_attr "predicable" "yes")
425    (set_attr "type" "fdivs")]
428 (define_insn "*divdf3_vfp"
429   [(set (match_operand:DF         0 "s_register_operand" "+w")
430         (div:DF (match_operand:DF 1 "s_register_operand" "w")
431                 (match_operand:DF 2 "s_register_operand" "w")))]
432   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
433   "fdivd%?\\t%P0, %P1, %P2"
434   [(set_attr "predicable" "yes")
435    (set_attr "type" "fdivd")]
439 ;; Multiplication insns
441 (define_insn "*mulsf3_vfp"
442   [(set (match_operand:SF          0 "s_register_operand" "+w")
443         (mult:SF (match_operand:SF 1 "s_register_operand" "w")
444                  (match_operand:SF 2 "s_register_operand" "w")))]
445   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
446   "fmuls%?\\t%0, %1, %2"
447   [(set_attr "predicable" "yes")
448    (set_attr "type" "farith")]
451 (define_insn "*muldf3_vfp"
452   [(set (match_operand:DF          0 "s_register_operand" "+w")
453         (mult:DF (match_operand:DF 1 "s_register_operand" "w")
454                  (match_operand:DF 2 "s_register_operand" "w")))]
455   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
456   "fmuld%?\\t%P0, %P1, %P2"
457   [(set_attr "predicable" "yes")
458    (set_attr "type" "fmul")]
462 (define_insn "*mulsf3negsf_vfp"
463   [(set (match_operand:SF                  0 "s_register_operand" "+w")
464         (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "w"))
465                  (match_operand:SF         2 "s_register_operand" "w")))]
466   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
467   "fnmuls%?\\t%0, %1, %2"
468   [(set_attr "predicable" "yes")
469    (set_attr "type" "farith")]
472 (define_insn "*muldf3negdf_vfp"
473   [(set (match_operand:DF                  0 "s_register_operand" "+w")
474         (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
475                  (match_operand:DF         2 "s_register_operand" "w")))]
476   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
477   "fnmuld%?\\t%P0, %P1, %P2"
478   [(set_attr "predicable" "yes")
479    (set_attr "type" "fmul")]
483 ;; Multiply-accumulate insns
485 ;; 0 = 1 * 2 + 0
486 (define_insn "*mulsf3addsf_vfp"
487   [(set (match_operand:SF                   0 "s_register_operand" "=w")
488         (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
489                           (match_operand:SF 3 "s_register_operand" "w"))
490                  (match_operand:SF          1 "s_register_operand" "0")))]
491   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
492   "fmacs%?\\t%0, %2, %3"
493   [(set_attr "predicable" "yes")
494    (set_attr "type" "farith")]
497 (define_insn "*muldf3adddf_vfp"
498   [(set (match_operand:DF                   0 "s_register_operand" "=w")
499         (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
500                           (match_operand:DF 3 "s_register_operand" "w"))
501                  (match_operand:DF          1 "s_register_operand" "0")))]
502   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
503   "fmacd%?\\t%P0, %P2, %P3"
504   [(set_attr "predicable" "yes")
505    (set_attr "type" "fmul")]
508 ;; 0 = 1 * 2 - 0
509 (define_insn "*mulsf3subsf_vfp"
510   [(set (match_operand:SF                    0 "s_register_operand" "=w")
511         (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
512                            (match_operand:SF 3 "s_register_operand" "w"))
513                   (match_operand:SF          1 "s_register_operand" "0")))]
514   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
515   "fmscs%?\\t%0, %2, %3"
516   [(set_attr "predicable" "yes")
517    (set_attr "type" "farith")]
520 (define_insn "*muldf3subdf_vfp"
521   [(set (match_operand:DF                    0 "s_register_operand" "=w")
522         (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
523                            (match_operand:DF 3 "s_register_operand" "w"))
524                   (match_operand:DF          1 "s_register_operand" "0")))]
525   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
526   "fmscd%?\\t%P0, %P2, %P3"
527   [(set_attr "predicable" "yes")
528    (set_attr "type" "fmul")]
531 ;; 0 = -(1 * 2) + 0
532 (define_insn "*mulsf3negsfaddsf_vfp"
533   [(set (match_operand:SF                    0 "s_register_operand" "=w")
534         (minus:SF (match_operand:SF          1 "s_register_operand" "0")
535                   (mult:SF (match_operand:SF 2 "s_register_operand" "w")
536                            (match_operand:SF 3 "s_register_operand" "w"))))]
537   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
538   "fnmacs%?\\t%0, %2, %3"
539   [(set_attr "predicable" "yes")
540    (set_attr "type" "farith")]
543 (define_insn "*fmuldf3negdfadddf_vfp"
544   [(set (match_operand:DF                    0 "s_register_operand" "=w")
545         (minus:DF (match_operand:DF          1 "s_register_operand" "0")
546                   (mult:DF (match_operand:DF 2 "s_register_operand" "w")
547                            (match_operand:DF 3 "s_register_operand" "w"))))]
548   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
549   "fnmacd%?\\t%P0, %P2, %P3"
550   [(set_attr "predicable" "yes")
551    (set_attr "type" "fmul")]
555 ;; 0 = -(1 * 2) - 0
556 (define_insn "*mulsf3negsfsubsf_vfp"
557   [(set (match_operand:SF                     0 "s_register_operand" "=w")
558         (minus:SF (mult:SF
559                     (neg:SF (match_operand:SF 2 "s_register_operand" "w"))
560                     (match_operand:SF         3 "s_register_operand" "w"))
561                   (match_operand:SF           1 "s_register_operand" "0")))]
562   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
563   "fnmscs%?\\t%0, %2, %3"
564   [(set_attr "predicable" "yes")
565    (set_attr "type" "farith")]
568 (define_insn "*muldf3negdfsubdf_vfp"
569   [(set (match_operand:DF                     0 "s_register_operand" "=w")
570         (minus:DF (mult:DF
571                     (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
572                     (match_operand:DF         3 "s_register_operand" "w"))
573                   (match_operand:DF           1 "s_register_operand" "0")))]
574   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
575   "fnmscd%?\\t%P0, %P2, %P3"
576   [(set_attr "predicable" "yes")
577    (set_attr "type" "fmul")]
581 ;; Conversion routines
583 (define_insn "*extendsfdf2_vfp"
584   [(set (match_operand:DF                  0 "s_register_operand" "=w")
585         (float_extend:DF (match_operand:SF 1 "s_register_operand" "w")))]
586   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
587   "fcvtds%?\\t%P0, %1"
588   [(set_attr "predicable" "yes")
589    (set_attr "type" "f_cvt")]
592 (define_insn "*truncdfsf2_vfp"
593   [(set (match_operand:SF                  0 "s_register_operand" "=w")
594         (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
595   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
596   "fcvtsd%?\\t%0, %P1"
597   [(set_attr "predicable" "yes")
598    (set_attr "type" "f_cvt")]
601 (define_insn "*truncsisf2_vfp"
602   [(set (match_operand:SI                 0 "s_register_operand" "=w")
603         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
604   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
605   "ftosizs%?\\t%0, %1"
606   [(set_attr "predicable" "yes")
607    (set_attr "type" "f_cvt")]
610 (define_insn "*truncsidf2_vfp"
611   [(set (match_operand:SI                 0 "s_register_operand" "=w")
612         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
613   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
614   "ftosizd%?\\t%0, %P1"
615   [(set_attr "predicable" "yes")
616    (set_attr "type" "f_cvt")]
620 (define_insn "fixuns_truncsfsi2"
621   [(set (match_operand:SI                 0 "s_register_operand" "=w")
622         (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
623   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
624   "ftouizs%?\\t%0, %1"
625   [(set_attr "predicable" "yes")
626    (set_attr "type" "f_cvt")]
629 (define_insn "fixuns_truncdfsi2"
630   [(set (match_operand:SI                 0 "s_register_operand" "=w")
631         (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
632   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
633   "ftouizd%?\\t%0, %P1"
634   [(set_attr "predicable" "yes")
635    (set_attr "type" "f_cvt")]
639 (define_insn "*floatsisf2_vfp"
640   [(set (match_operand:SF           0 "s_register_operand" "=w")
641         (float:SF (match_operand:SI 1 "s_register_operand" "w")))]
642   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
643   "fsitos%?\\t%0, %1"
644   [(set_attr "predicable" "yes")
645    (set_attr "type" "f_cvt")]
648 (define_insn "*floatsidf2_vfp"
649   [(set (match_operand:DF           0 "s_register_operand" "=w")
650         (float:DF (match_operand:SI 1 "s_register_operand" "w")))]
651   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
652   "fsitod%?\\t%P0, %1"
653   [(set_attr "predicable" "yes")
654    (set_attr "type" "f_cvt")]
658 (define_insn "floatunssisf2"
659   [(set (match_operand:SF           0 "s_register_operand" "=w")
660         (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "w")))]
661   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
662   "fuitos%?\\t%0, %1"
663   [(set_attr "predicable" "yes")
664    (set_attr "type" "f_cvt")]
667 (define_insn "floatunssidf2"
668   [(set (match_operand:DF           0 "s_register_operand" "=w")
669         (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "w")))]
670   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
671   "fuitod%?\\t%P0, %1"
672   [(set_attr "predicable" "yes")
673    (set_attr "type" "f_cvt")]
677 ;; Sqrt insns.
679 (define_insn "*sqrtsf2_vfp"
680   [(set (match_operand:SF          0 "s_register_operand" "=w")
681         (sqrt:SF (match_operand:SF 1 "s_register_operand" "w")))]
682   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
683   "fsqrts%?\\t%0, %1"
684   [(set_attr "predicable" "yes")
685    (set_attr "type" "fdivs")]
688 (define_insn "*sqrtdf2_vfp"
689   [(set (match_operand:DF          0 "s_register_operand" "=w")
690         (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
691   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
692   "fsqrtd%?\\t%P0, %P1"
693   [(set_attr "predicable" "yes")
694    (set_attr "type" "fdivd")]
698 ;; Patterns to split/copy vfp condition flags.
700 (define_insn "*movcc_vfp"
701   [(set (reg CC_REGNUM)
702         (reg VFPCC_REGNUM))]
703   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
704   "fmstat%?"
705   [(set_attr "conds" "set")
706    (set_attr "type" "f_flag")]
709 (define_insn_and_split "*cmpsf_split_vfp"
710   [(set (reg:CCFP CC_REGNUM)
711         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w")
712                       (match_operand:SF 1 "vfp_compare_operand" "wG")))]
713   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
714   "#"
715   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
716   [(set (reg:CCFP VFPCC_REGNUM)
717         (compare:CCFP (match_dup 0)
718                       (match_dup 1)))
719    (set (reg:CCFP CC_REGNUM)
720         (reg:CCFP VFPCC_REGNUM))]
721   ""
724 (define_insn_and_split "*cmpsf_trap_split_vfp"
725   [(set (reg:CCFPE CC_REGNUM)
726         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w")
727                        (match_operand:SF 1 "vfp_compare_operand" "wG")))]
728   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
729   "#"
730   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
731   [(set (reg:CCFPE VFPCC_REGNUM)
732         (compare:CCFPE (match_dup 0)
733                        (match_dup 1)))
734    (set (reg:CCFPE CC_REGNUM)
735         (reg:CCFPE VFPCC_REGNUM))]
736   ""
739 (define_insn_and_split "*cmpdf_split_vfp"
740   [(set (reg:CCFP CC_REGNUM)
741         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w")
742                       (match_operand:DF 1 "vfp_compare_operand" "wG")))]
743   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
744   "#"
745   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
746   [(set (reg:CCFP VFPCC_REGNUM)
747         (compare:CCFP (match_dup 0)
748                        (match_dup 1)))
749    (set (reg:CCFP CC_REGNUM)
750         (reg:CCFPE VFPCC_REGNUM))]
751   ""
754 (define_insn_and_split "*cmpdf_trap_split_vfp"
755   [(set (reg:CCFPE CC_REGNUM)
756         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w")
757                        (match_operand:DF 1 "vfp_compare_operand" "wG")))]
758   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
759   "#"
760   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
761   [(set (reg:CCFPE VFPCC_REGNUM)
762         (compare:CCFPE (match_dup 0)
763                        (match_dup 1)))
764    (set (reg:CCFPE CC_REGNUM)
765         (reg:CCFPE VFPCC_REGNUM))]
766   ""
770 ;; Comparison patterns
772 (define_insn "*cmpsf_vfp"
773   [(set (reg:CCFP VFPCC_REGNUM)
774         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w,w")
775                       (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
776   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
777   "@
778    fcmps%?\\t%0, %1
779    fcmpzs%?\\t%0"
780   [(set_attr "predicable" "yes")
781    (set_attr "type" "ffarith")]
784 (define_insn "*cmpsf_trap_vfp"
785   [(set (reg:CCFPE VFPCC_REGNUM)
786         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w,w")
787                        (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
788   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
789   "@
790    fcmpes%?\\t%0, %1
791    fcmpezs%?\\t%0"
792   [(set_attr "predicable" "yes")
793    (set_attr "type" "ffarith")]
796 (define_insn "*cmpdf_vfp"
797   [(set (reg:CCFP VFPCC_REGNUM)
798         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w,w")
799                       (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
800   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
801   "@
802    fcmpd%?\\t%P0, %P1
803    fcmpzd%?\\t%P0"
804   [(set_attr "predicable" "yes")
805    (set_attr "type" "ffarith")]
808 (define_insn "*cmpdf_trap_vfp"
809   [(set (reg:CCFPE VFPCC_REGNUM)
810         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w,w")
811                        (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
812   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
813   "@
814    fcmped%?\\t%P0, %P1
815    fcmpezd%?\\t%P0"
816   [(set_attr "predicable" "yes")
817    (set_attr "type" "ffarith")]
821 ;; Store multiple insn used in function prologue.
823 (define_insn "*push_multi_vfp"
824   [(match_parallel 2 "multi_register_push"
825     [(set (match_operand:BLK 0 "memory_operand" "=m")
826           (unspec:BLK [(match_operand:DF 1 "s_register_operand" "w")]
827                       UNSPEC_PUSH_MULT))])]
828   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
829   "* return vfp_output_fstmx (operands);"
830   [(set_attr "type" "f_stored")]
834 ;; Unimplemented insns:
835 ;; fldm*
836 ;; fstm*
837 ;; fmdhr et al (VFPv1)
838 ;; Support for xD (single precision only) variants.
839 ;; fmrrs, fmsrr