Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / gcc / config / arm / vfp.md
blobfb20dd197605ba3735ed007cc30a803a783a6999
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, 59 Temple Place - Suite 330, Boston, MA
20 ;; 02111-1307, 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 ;; The VFP "type" attributes differ from those used in the FPA model.
59 ;; ffarith      Fast floating point insns, e.g. abs, neg, cpy, cmp.
60 ;; farith       Most arithmetic insns.
61 ;; fmul         Double precision multiply.
62 ;; fdivs        Single precision sqrt or division.
63 ;; fdivd        Double precision sqrt or division.
64 ;; f_load       Floating point load from memory.
65 ;; f_store      Floating point store to memory.
66 ;; f_2_r        Transfer vfp to arm reg.
67 ;; r_2_f        Transfer arm to vfp reg.
69 (define_insn_reservation "vfp_ffarith" 4
70  (and (eq_attr "fpu" "vfp")
71       (eq_attr "type" "ffarith"))
72  "fmac")
74 (define_insn_reservation "vfp_farith" 8
75  (and (eq_attr "fpu" "vfp")
76       (eq_attr "type" "farith"))
77  "fmac")
79 (define_insn_reservation "vfp_fmul" 9
80  (and (eq_attr "fpu" "vfp")
81       (eq_attr "type" "fmul"))
82  "fmac*2")
84 (define_insn_reservation "vfp_fdivs" 19
85  (and (eq_attr "fpu" "vfp")
86       (eq_attr "type" "fdivs"))
87  "ds*15")
89 (define_insn_reservation "vfp_fdivd" 33
90  (and (eq_attr "fpu" "vfp")
91       (eq_attr "type" "fdivd"))
92  "fmac+ds*29")
94 ;; Moves to/from arm regs also use the load/store pipeline.
95 (define_insn_reservation "vfp_fload" 4
96  (and (eq_attr "fpu" "vfp")
97       (eq_attr "type" "f_load,r_2_f"))
98  "vfp_ls")
100 (define_insn_reservation "vfp_fstore" 4
101  (and (eq_attr "fpu" "vfp")
102       (eq_attr "type" "f_load,f_2_r"))
103  "vfp_ls")
106 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
107 ;; Insn pattern
108 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
110 ;; SImode moves
111 ;; ??? For now do not allow loading constants into vfp regs.  This causes
112 ;; problems because small constants get converted into adds.
113 (define_insn "*arm_movsi_vfp"
114   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r ,m,*w,r,*w,*w, *Uv")
115       (match_operand:SI 1 "general_operand"        "rI,K,mi,r,r,*w,*w,*Uvi,*w"))]
116   "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
117    && (   s_register_operand (operands[0], SImode)
118        || s_register_operand (operands[1], SImode))"
119   "@
120   mov%?\\t%0, %1
121   mvn%?\\t%0, #%B1
122   ldr%?\\t%0, %1
123   str%?\\t%1, %0
124   fmsr%?\\t%0, %1\\t%@ int
125   fmrs%?\\t%0, %1\\t%@ int
126   fcpys%?\\t%0, %1\\t%@ int
127   flds%?\\t%0, %1\\t%@ int
128   fsts%?\\t%1, %0\\t%@ int"
129   [(set_attr "predicable" "yes")
130    (set_attr "type" "*,*,load1,store1,r_2_f,f_2_r,ffarith,f_load,f_store")
131    (set_attr "pool_range"     "*,*,4096,*,*,*,*,1020,*")
132    (set_attr "neg_pool_range" "*,*,4084,*,*,*,*,1008,*")]
136 ;; DImode moves
138 (define_insn "*arm_movdi_vfp"
139   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,m,w,r,w,w, Uv")
140         (match_operand:DI 1 "di_operand"              "rIK,mi,r,r,w,w,Uvi,w"))]
141   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
142   "*
143   switch (which_alternative)
144     {
145     case 0: case 1: case 2:
146       return (output_move_double (operands));
147     case 3:
148       return \"fmdrr%?\\t%P0, %1\\t%@ int\";
149     case 4:
150       return \"fmrrd%?\\t%0, %1\\t%@ int\";
151     case 5:
152       return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
153     case 6:
154       return \"fldd%?\\t%P0, %1\\t%@ int\";
155     case 7:
156       return \"fstd%?\\t%P1, %0\\t%@ int\";
157     default:
158       abort ();
159     }
160   "
161   [(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarith,f_load,f_store")
162    (set_attr "length" "8,8,8,4,4,4,4,4")
163    (set_attr "pool_range"     "*,1020,*,*,*,*,1020,*")
164    (set_attr "neg_pool_range" "*,1008,*,*,*,*,1008,*")]
168 ;; SFmode moves
170 (define_insn "*movsf_vfp"
171   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,r,w  ,Uv,r ,m,w,r")
172         (match_operand:SF 1 "general_operand"      " r,w,UvE,w, mE,r,w,r"))]
173   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
174    && (   s_register_operand (operands[0], SFmode)
175        || s_register_operand (operands[1], SFmode))"
176   "@
177   fmsr%?\\t%0, %1
178   fmrs%?\\t%0, %1
179   flds%?\\t%0, %1
180   fsts%?\\t%1, %0
181   ldr%?\\t%0, %1\\t%@ float
182   str%?\\t%1, %0\\t%@ float
183   fcpys%?\\t%0, %1
184   mov%?\\t%0, %1\\t%@ float"
185   [(set_attr "predicable" "yes")
186    (set_attr "type" "r_2_f,f_2_r,ffarith,*,f_load,f_store,load1,store1")
187    (set_attr "pool_range" "*,*,1020,*,4096,*,*,*")
188    (set_attr "neg_pool_range" "*,*,1008,*,4080,*,*,*")]
192 ;; DFmode moves
194 (define_insn "*movdf_vfp"
195   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,r,r, m,w  ,Uv,w,r")
196         (match_operand:DF 1 "soft_df_operand"              " r,w,mF,r,UvF,w, w,r"))]
197   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
198   "*
199   {
200     switch (which_alternative)
201       {
202       case 0:
203         return \"fmdrr%?\\t%P0, %Q1, %R1\";
204       case 1:
205         return \"fmrrd%?\\t%Q0, %R0, %P1\";
206       case 2: case 3: case 7:
207         return output_move_double (operands);
208       case 4:
209         return \"fldd%?\\t%P0, %1\";
210       case 5:
211         return \"fstd%?\\t%P1, %0\";
212       case 6:
213         return \"fcpyd%?\\t%P0, %P1\";
214       default:
215         abort ();
216       }
217     }
218   "
219   [(set_attr "type" "r_2_f,f_2_r,ffarith,*,load2,store2,f_load,f_store")
220    (set_attr "length" "4,4,8,8,4,4,4,8")
221    (set_attr "pool_range" "*,*,1020,*,1020,*,*,*")
222    (set_attr "neg_pool_range" "*,*,1008,*,1008,*,*,*")]
226 ;; Conditional move patterns
228 (define_insn "*movsfcc_vfp"
229   [(set (match_operand:SF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
230         (if_then_else:SF
231           (match_operator   3 "arm_comparison_operator"
232             [(match_operand 4 "cc_register" "") (const_int 0)])
233           (match_operand:SF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
234           (match_operand:SF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
235   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
236   "@
237    fcpys%D3\\t%0, %2
238    fcpys%d3\\t%0, %1
239    fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
240    fmsr%D3\\t%0, %2
241    fmsr%d3\\t%0, %1
242    fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
243    fmrs%D3\\t%0, %2
244    fmrs%d3\\t%0, %1
245    fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
246    [(set_attr "conds" "use")
247     (set_attr "length" "4,4,8,4,4,8,4,4,8")
248     (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
251 (define_insn "*movdfcc_vfp"
252   [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
253         (if_then_else:DF
254           (match_operator   3 "arm_comparison_operator"
255             [(match_operand 4 "cc_register" "") (const_int 0)])
256           (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
257           (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
258   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
259   "@
260    fcpyd%D3\\t%P0, %P2
261    fcpyd%d3\\t%P0, %P1
262    fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
263    fmdrr%D3\\t%P0, %Q2, %R2
264    fmdrr%d3\\t%P0, %Q1, %R1
265    fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
266    fmrrd%D3\\t%Q0, %R0, %P2
267    fmrrd%d3\\t%Q0, %R0, %P1
268    fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
269    [(set_attr "conds" "use")
270     (set_attr "length" "4,4,8,4,4,8,4,4,8")
271     (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
275 ;; Sign manipulation functions
277 (define_insn "*abssf2_vfp"
278   [(set (match_operand:SF         0 "s_register_operand" "=w")
279         (abs:SF (match_operand:SF 1 "s_register_operand" "w")))]
280   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
281   "fabss%?\\t%0, %1"
282   [(set_attr "predicable" "yes")
283    (set_attr "type" "ffarith")]
286 (define_insn "*absdf2_vfp"
287   [(set (match_operand:DF         0 "s_register_operand" "=w")
288         (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
289   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
290   "fabsd%?\\t%P0, %P1"
291   [(set_attr "predicable" "yes")
292    (set_attr "type" "ffarith")]
295 (define_insn "*negsf2_vfp"
296   [(set (match_operand:SF         0 "s_register_operand" "+w")
297         (neg:SF (match_operand:SF 1 "s_register_operand" "w")))]
298   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
299   "fnegs%?\\t%0, %1"
300   [(set_attr "predicable" "yes")
301    (set_attr "type" "ffarith")]
304 (define_insn "*negdf2_vfp"
305   [(set (match_operand:DF         0 "s_register_operand" "+w")
306         (neg:DF (match_operand:DF 1 "s_register_operand" "w")))]
307   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
308   "fnegd%?\\t%P0, %P1"
309   [(set_attr "predicable" "yes")
310    (set_attr "type" "ffarith")]
314 ;; Arithmetic insns
316 (define_insn "*addsf3_vfp"
317   [(set (match_operand:SF          0 "s_register_operand" "=w")
318         (plus:SF (match_operand:SF 1 "s_register_operand" "w")
319                  (match_operand:SF 2 "s_register_operand" "w")))]
320   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
321   "fadds%?\\t%0, %1, %2"
322   [(set_attr "predicable" "yes")
323    (set_attr "type" "farith")]
326 (define_insn "*adddf3_vfp"
327   [(set (match_operand:DF          0 "s_register_operand" "=w")
328         (plus:DF (match_operand:DF 1 "s_register_operand" "w")
329                  (match_operand:DF 2 "s_register_operand" "w")))]
330   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
331   "faddd%?\\t%P0, %P1, %P2"
332   [(set_attr "predicable" "yes")
333    (set_attr "type" "farith")]
337 (define_insn "*subsf3_vfp"
338   [(set (match_operand:SF           0 "s_register_operand" "=w")
339         (minus:SF (match_operand:SF 1 "s_register_operand" "w")
340                   (match_operand:SF 2 "s_register_operand" "w")))]
341   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
342   "fsubs%?\\t%0, %1, %2"
343   [(set_attr "predicable" "yes")
344    (set_attr "type" "farith")]
347 (define_insn "*subdf3_vfp"
348   [(set (match_operand:DF           0 "s_register_operand" "=w")
349         (minus:DF (match_operand:DF 1 "s_register_operand" "w")
350                   (match_operand:DF 2 "s_register_operand" "w")))]
351   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
352   "fsubd%?\\t%P0, %P1, %P2"
353   [(set_attr "predicable" "yes")
354    (set_attr "type" "farith")]
358 ;; Division insns
360 (define_insn "*divsf3_vfp"
361   [(set (match_operand:SF         0 "s_register_operand" "+w")
362         (div:SF (match_operand:SF 1 "s_register_operand" "w")
363                 (match_operand:SF 2 "s_register_operand" "w")))]
364   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
365   "fdivs%?\\t%0, %1, %2"
366   [(set_attr "predicable" "yes")
367    (set_attr "type" "fdivs")]
370 (define_insn "*divdf3_vfp"
371   [(set (match_operand:DF         0 "s_register_operand" "+w")
372         (div:DF (match_operand:DF 1 "s_register_operand" "w")
373                 (match_operand:DF 2 "s_register_operand" "w")))]
374   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
375   "fdivd%?\\t%P0, %P1, %P2"
376   [(set_attr "predicable" "yes")
377    (set_attr "type" "fdivd")]
381 ;; Multiplication insns
383 (define_insn "*mulsf3_vfp"
384   [(set (match_operand:SF          0 "s_register_operand" "+w")
385         (mult:SF (match_operand:SF 1 "s_register_operand" "w")
386                  (match_operand:SF 2 "s_register_operand" "w")))]
387   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
388   "fmuls%?\\t%0, %1, %2"
389   [(set_attr "predicable" "yes")
390    (set_attr "type" "farith")]
393 (define_insn "*muldf3_vfp"
394   [(set (match_operand:DF          0 "s_register_operand" "+w")
395         (mult:DF (match_operand:DF 1 "s_register_operand" "w")
396                  (match_operand:DF 2 "s_register_operand" "w")))]
397   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
398   "fmuld%?\\t%P0, %P1, %P2"
399   [(set_attr "predicable" "yes")
400    (set_attr "type" "fmul")]
404 (define_insn "*mulsf3negsf_vfp"
405   [(set (match_operand:SF                  0 "s_register_operand" "+w")
406         (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "w"))
407                  (match_operand:SF         2 "s_register_operand" "w")))]
408   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
409   "fnmuls%?\\t%0, %1, %2"
410   [(set_attr "predicable" "yes")
411    (set_attr "type" "farith")]
414 (define_insn "*muldf3negdf_vfp"
415   [(set (match_operand:DF                  0 "s_register_operand" "+w")
416         (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
417                  (match_operand:DF         2 "s_register_operand" "w")))]
418   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
419   "fnmuld%?\\t%P0, %P1, %P2"
420   [(set_attr "predicable" "yes")
421    (set_attr "type" "fmul")]
425 ;; Multiply-accumulate insns
427 ;; 0 = 1 * 2 + 0
428 (define_insn "*mulsf3addsf_vfp"
429   [(set (match_operand:SF                   0 "s_register_operand" "=w")
430         (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
431                           (match_operand:SF 3 "s_register_operand" "w"))
432                  (match_operand:SF          1 "s_register_operand" "0")))]
433   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
434   "fmacs%?\\t%0, %2, %3"
435   [(set_attr "predicable" "yes")
436    (set_attr "type" "farith")]
439 (define_insn "*muldf3adddf_vfp"
440   [(set (match_operand:DF                   0 "s_register_operand" "=w")
441         (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
442                           (match_operand:DF 3 "s_register_operand" "w"))
443                  (match_operand:DF          1 "s_register_operand" "0")))]
444   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
445   "fmacd%?\\t%P0, %P2, %P3"
446   [(set_attr "predicable" "yes")
447    (set_attr "type" "fmul")]
450 ;; 0 = 1 * 2 - 0
451 (define_insn "*mulsf3subsf_vfp"
452   [(set (match_operand:SF                    0 "s_register_operand" "=w")
453         (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
454                            (match_operand:SF 3 "s_register_operand" "w"))
455                   (match_operand:SF          1 "s_register_operand" "0")))]
456   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
457   "fmscs%?\\t%0, %2, %3"
458   [(set_attr "predicable" "yes")
459    (set_attr "type" "farith")]
462 (define_insn "*muldf3subdf_vfp"
463   [(set (match_operand:DF                    0 "s_register_operand" "=w")
464         (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
465                            (match_operand:DF 3 "s_register_operand" "w"))
466                   (match_operand:DF          1 "s_register_operand" "0")))]
467   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
468   "fmscd%?\\t%P0, %P2, %P3"
469   [(set_attr "predicable" "yes")
470    (set_attr "type" "fmul")]
473 ;; 0 = -(1 * 2) + 0
474 (define_insn "*mulsf3negsfaddsf_vfp"
475   [(set (match_operand:SF                    0 "s_register_operand" "=w")
476         (minus:SF (match_operand:SF          1 "s_register_operand" "0")
477                   (mult:SF (match_operand:SF 2 "s_register_operand" "w")
478                            (match_operand:SF 3 "s_register_operand" "w"))))]
479   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
480   "fnmacs%?\\t%0, %2, %3"
481   [(set_attr "predicable" "yes")
482    (set_attr "type" "farith")]
485 (define_insn "*fmuldf3negdfadddf_vfp"
486   [(set (match_operand:DF                    0 "s_register_operand" "=w")
487         (minus:DF (match_operand:DF          1 "s_register_operand" "0")
488                   (mult:DF (match_operand:DF 2 "s_register_operand" "w")
489                            (match_operand:DF 3 "s_register_operand" "w"))))]
490   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
491   "fnmacd%?\\t%P0, %P2, %P3"
492   [(set_attr "predicable" "yes")
493    (set_attr "type" "fmul")]
497 ;; 0 = -(1 * 2) - 0
498 (define_insn "*mulsf3negsfsubsf_vfp"
499   [(set (match_operand:SF                     0 "s_register_operand" "=w")
500         (minus:SF (mult:SF
501                     (neg:SF (match_operand:SF 2 "s_register_operand" "w"))
502                     (match_operand:SF         3 "s_register_operand" "w"))
503                   (match_operand:SF           1 "s_register_operand" "0")))]
504   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
505   "fnmscs%?\\t%0, %2, %3"
506   [(set_attr "predicable" "yes")
507    (set_attr "type" "farith")]
510 (define_insn "*muldf3negdfsubdf_vfp"
511   [(set (match_operand:DF                     0 "s_register_operand" "=w")
512         (minus:DF (mult:DF
513                     (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
514                     (match_operand:DF         3 "s_register_operand" "w"))
515                   (match_operand:DF           1 "s_register_operand" "0")))]
516   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
517   "fnmscd%?\\t%P0, %P2, %P3"
518   [(set_attr "predicable" "yes")
519    (set_attr "type" "fmul")]
523 ;; Conversion routines
525 (define_insn "*extendsfdf2_vfp"
526   [(set (match_operand:DF                  0 "s_register_operand" "=w")
527         (float_extend:DF (match_operand:SF 1 "s_register_operand" "w")))]
528   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
529   "fcvtds%?\\t%P0, %1"
530   [(set_attr "predicable" "yes")
531    (set_attr "type" "farith")]
534 (define_insn "*truncdfsf2_vfp"
535   [(set (match_operand:SF                  0 "s_register_operand" "=w")
536         (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
537   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
538   "fcvtsd%?\\t%0, %P1"
539   [(set_attr "predicable" "yes")
540    (set_attr "type" "farith")]
543 (define_insn "*truncsisf2_vfp"
544   [(set (match_operand:SI                 0 "s_register_operand" "=w")
545         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
546   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
547   "ftosizs%?\\t%0, %1"
548   [(set_attr "predicable" "yes")
549    (set_attr "type" "farith")]
552 (define_insn "*truncsidf2_vfp"
553   [(set (match_operand:SI                 0 "s_register_operand" "=w")
554         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
555   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
556   "ftosizd%?\\t%0, %P1"
557   [(set_attr "predicable" "yes")
558    (set_attr "type" "farith")]
562 (define_insn "fixuns_truncsfsi2"
563   [(set (match_operand:SI                 0 "s_register_operand" "=w")
564         (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
565   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
566   "ftouizs%?\\t%0, %1"
567   [(set_attr "predicable" "yes")
568    (set_attr "type" "farith")]
571 (define_insn "fixuns_truncdfsi2"
572   [(set (match_operand:SI                 0 "s_register_operand" "=w")
573         (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
574   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
575   "ftouizd%?\\t%0, %P1"
576   [(set_attr "predicable" "yes")
577    (set_attr "type" "farith")]
581 (define_insn "*floatsisf2_vfp"
582   [(set (match_operand:SF           0 "s_register_operand" "=w")
583         (float:SF (match_operand:SI 1 "s_register_operand" "w")))]
584   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
585   "fsitos%?\\t%0, %1"
586   [(set_attr "predicable" "yes")
587    (set_attr "type" "farith")]
590 (define_insn "*floatsidf2_vfp"
591   [(set (match_operand:DF           0 "s_register_operand" "=w")
592         (float:DF (match_operand:SI 1 "s_register_operand" "w")))]
593   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
594   "fsitod%?\\t%P0, %1"
595   [(set_attr "predicable" "yes")
596    (set_attr "type" "farith")]
600 (define_insn "floatunssisf2"
601   [(set (match_operand:SF           0 "s_register_operand" "=w")
602         (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "w")))]
603   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
604   "fuitos%?\\t%0, %1"
605   [(set_attr "predicable" "yes")
606    (set_attr "type" "farith")]
609 (define_insn "floatunssidf2"
610   [(set (match_operand:DF           0 "s_register_operand" "=w")
611         (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "w")))]
612   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
613   "fuitod%?\\t%P0, %1"
614   [(set_attr "predicable" "yes")
615    (set_attr "type" "farith")]
619 ;; Sqrt insns.
621 (define_insn "*sqrtsf2_vfp"
622   [(set (match_operand:SF          0 "s_register_operand" "=w")
623         (sqrt:SF (match_operand:SF 1 "s_register_operand" "w")))]
624   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
625   "fsqrts%?\\t%0, %1"
626   [(set_attr "predicable" "yes")
627    (set_attr "type" "fdivs")]
630 (define_insn "*sqrtdf2_vfp"
631   [(set (match_operand:DF          0 "s_register_operand" "=w")
632         (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
633   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
634   "fsqrtd%?\\t%P0, %P1"
635   [(set_attr "predicable" "yes")
636    (set_attr "type" "fdivd")]
640 ;; Patterns to split/copy vfp condition flags.
642 (define_insn "*movcc_vfp"
643   [(set (reg CC_REGNUM)
644         (reg VFPCC_REGNUM))]
645   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
646   "fmstat%?"
647   [(set_attr "conds" "set")
648    (set_attr "type" "ffarith")]
651 (define_insn_and_split "*cmpsf_split_vfp"
652   [(set (reg:CCFP CC_REGNUM)
653         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w")
654                       (match_operand:SF 1 "vfp_compare_operand" "wG")))]
655   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
656   "#"
657   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
658   [(set (reg:CCFP VFPCC_REGNUM)
659         (compare:CCFP (match_dup 0)
660                       (match_dup 1)))
661    (set (reg:CCFP CC_REGNUM)
662         (reg:CCFP VFPCC_REGNUM))]
663   ""
666 (define_insn_and_split "*cmpsf_trap_split_vfp"
667   [(set (reg:CCFPE CC_REGNUM)
668         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w")
669                        (match_operand:SF 1 "vfp_compare_operand" "wG")))]
670   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
671   "#"
672   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
673   [(set (reg:CCFPE VFPCC_REGNUM)
674         (compare:CCFPE (match_dup 0)
675                        (match_dup 1)))
676    (set (reg:CCFPE CC_REGNUM)
677         (reg:CCFPE VFPCC_REGNUM))]
678   ""
681 (define_insn_and_split "*cmpdf_split_vfp"
682   [(set (reg:CCFP CC_REGNUM)
683         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w")
684                       (match_operand:DF 1 "vfp_compare_operand" "wG")))]
685   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
686   "#"
687   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
688   [(set (reg:CCFP VFPCC_REGNUM)
689         (compare:CCFP (match_dup 0)
690                        (match_dup 1)))
691    (set (reg:CCFP CC_REGNUM)
692         (reg:CCFPE VFPCC_REGNUM))]
693   ""
696 (define_insn_and_split "*cmpdf_trap_split_vfp"
697   [(set (reg:CCFPE CC_REGNUM)
698         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w")
699                        (match_operand:DF 1 "vfp_compare_operand" "wG")))]
700   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
701   "#"
702   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
703   [(set (reg:CCFPE VFPCC_REGNUM)
704         (compare:CCFPE (match_dup 0)
705                        (match_dup 1)))
706    (set (reg:CCFPE CC_REGNUM)
707         (reg:CCFPE VFPCC_REGNUM))]
708   ""
712 ;; Comparison patterns
714 (define_insn "*cmpsf_vfp"
715   [(set (reg:CCFP VFPCC_REGNUM)
716         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w,w")
717                       (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
718   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
719   "@
720    fcmps%?\\t%0, %1
721    fcmpzs%?\\t%0"
722   [(set_attr "predicable" "yes")
723    (set_attr "type" "ffarith")]
726 (define_insn "*cmpsf_trap_vfp"
727   [(set (reg:CCFPE VFPCC_REGNUM)
728         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w,w")
729                        (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
730   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
731   "@
732    fcmpes%?\\t%0, %1
733    fcmpezs%?\\t%0"
734   [(set_attr "predicable" "yes")
735    (set_attr "type" "ffarith")]
738 (define_insn "*cmpdf_vfp"
739   [(set (reg:CCFP VFPCC_REGNUM)
740         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w,w")
741                       (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
742   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
743   "@
744    fcmpd%?\\t%P0, %P1
745    fcmpzd%?\\t%P0"
746   [(set_attr "predicable" "yes")
747    (set_attr "type" "ffarith")]
750 (define_insn "*cmpdf_trap_vfp"
751   [(set (reg:CCFPE VFPCC_REGNUM)
752         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w,w")
753                        (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
754   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
755   "@
756    fcmped%?\\t%P0, %P1
757    fcmpezd%?\\t%P0"
758   [(set_attr "predicable" "yes")
759    (set_attr "type" "ffarith")]
763 ;; Store multiple insn used in function prologue.
765 (define_insn "*push_multi_vfp"
766   [(match_parallel 2 "multi_register_push"
767     [(set (match_operand:BLK 0 "memory_operand" "=m")
768           (unspec:BLK [(match_operand:DF 1 "s_register_operand" "w")]
769                       UNSPEC_PUSH_MULT))])]
770   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
771   "* return vfp_output_fstmx (operands);"
772   [(set_attr "type" "f_store")]
776 ;; Unimplemented insns:
777 ;; fldm*
778 ;; fstm*
779 ;; fmdhr et al (VFPv1)
780 ;; Support for xD (single precision only) variants.
781 ;; fmrrs, fmsrr