Update FSF address.
[official-gcc.git] / gcc / config / arm / vfp.md
blob5809a4531edc3ec7f09759d42e3f62691117c6f8
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   "*
153   switch (which_alternative)
154     {
155     case 0: 
156       return \"#\";
157     case 1:
158     case 2:
159       return output_move_double (operands);
160     case 3:
161       return \"fmdrr%?\\t%P0, %1\\t%@ int\";
162     case 4:
163       return \"fmrrd%?\\t%0, %1\\t%@ int\";
164     case 5:
165       return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
166     case 6:
167       return \"fldd%?\\t%P0, %1\\t%@ int\";
168     case 7:
169       return \"fstd%?\\t%P1, %0\\t%@ int\";
170     default:
171       gcc_unreachable ();
172     }
173   "
174   [(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarith,f_loadd,f_stored")
175    (set_attr "length" "8,8,8,4,4,4,4,4")
176    (set_attr "pool_range"     "*,1020,*,*,*,*,1020,*")
177    (set_attr "neg_pool_range" "*,1008,*,*,*,*,1008,*")]
181 ;; SFmode moves
183 (define_insn "*movsf_vfp"
184   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,r,w  ,Uv,r ,m,w,r")
185         (match_operand:SF 1 "general_operand"      " r,w,UvE,w, mE,r,w,r"))]
186   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
187    && (   s_register_operand (operands[0], SFmode)
188        || s_register_operand (operands[1], SFmode))"
189   "@
190   fmsr%?\\t%0, %1
191   fmrs%?\\t%0, %1
192   flds%?\\t%0, %1
193   fsts%?\\t%1, %0
194   ldr%?\\t%0, %1\\t%@ float
195   str%?\\t%1, %0\\t%@ float
196   fcpys%?\\t%0, %1
197   mov%?\\t%0, %1\\t%@ float"
198   [(set_attr "predicable" "yes")
199    (set_attr "type" "r_2_f,f_2_r,ffarith,*,f_loads,f_stores,load1,store1")
200    (set_attr "pool_range" "*,*,1020,*,4096,*,*,*")
201    (set_attr "neg_pool_range" "*,*,1008,*,4080,*,*,*")]
205 ;; DFmode moves
207 (define_insn "*movdf_vfp"
208   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,r,r, m,w  ,Uv,w,r")
209         (match_operand:DF 1 "soft_df_operand"              " r,w,mF,r,UvF,w, w,r"))]
210   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
211   "*
212   {
213     switch (which_alternative)
214       {
215       case 0:
216         return \"fmdrr%?\\t%P0, %Q1, %R1\";
217       case 1:
218         return \"fmrrd%?\\t%Q0, %R0, %P1\";
219       case 2: case 3:
220         return output_move_double (operands);
221       case 4:
222         return \"fldd%?\\t%P0, %1\";
223       case 5:
224         return \"fstd%?\\t%P1, %0\";
225       case 6:
226         return \"fcpyd%?\\t%P0, %P1\";
227       case 7:
228         return \"#\";
229       default:
230         gcc_unreachable ();
231       }
232     }
233   "
234   [(set_attr "type" "r_2_f,f_2_r,ffarith,*,load2,store2,f_loadd,f_stored")
235    (set_attr "length" "4,4,8,8,4,4,4,8")
236    (set_attr "pool_range" "*,*,1020,*,1020,*,*,*")
237    (set_attr "neg_pool_range" "*,*,1008,*,1008,*,*,*")]
241 ;; Conditional move patterns
243 (define_insn "*movsfcc_vfp"
244   [(set (match_operand:SF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
245         (if_then_else:SF
246           (match_operator   3 "arm_comparison_operator"
247             [(match_operand 4 "cc_register" "") (const_int 0)])
248           (match_operand:SF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
249           (match_operand:SF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
250   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
251   "@
252    fcpys%D3\\t%0, %2
253    fcpys%d3\\t%0, %1
254    fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
255    fmsr%D3\\t%0, %2
256    fmsr%d3\\t%0, %1
257    fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
258    fmrs%D3\\t%0, %2
259    fmrs%d3\\t%0, %1
260    fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
261    [(set_attr "conds" "use")
262     (set_attr "length" "4,4,8,4,4,8,4,4,8")
263     (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
266 (define_insn "*movdfcc_vfp"
267   [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
268         (if_then_else:DF
269           (match_operator   3 "arm_comparison_operator"
270             [(match_operand 4 "cc_register" "") (const_int 0)])
271           (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
272           (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
273   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
274   "@
275    fcpyd%D3\\t%P0, %P2
276    fcpyd%d3\\t%P0, %P1
277    fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
278    fmdrr%D3\\t%P0, %Q2, %R2
279    fmdrr%d3\\t%P0, %Q1, %R1
280    fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
281    fmrrd%D3\\t%Q0, %R0, %P2
282    fmrrd%d3\\t%Q0, %R0, %P1
283    fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
284    [(set_attr "conds" "use")
285     (set_attr "length" "4,4,8,4,4,8,4,4,8")
286     (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
290 ;; Sign manipulation functions
292 (define_insn "*abssf2_vfp"
293   [(set (match_operand:SF         0 "s_register_operand" "=w")
294         (abs:SF (match_operand:SF 1 "s_register_operand" "w")))]
295   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
296   "fabss%?\\t%0, %1"
297   [(set_attr "predicable" "yes")
298    (set_attr "type" "ffarith")]
301 (define_insn "*absdf2_vfp"
302   [(set (match_operand:DF         0 "s_register_operand" "=w")
303         (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
304   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
305   "fabsd%?\\t%P0, %P1"
306   [(set_attr "predicable" "yes")
307    (set_attr "type" "ffarith")]
310 (define_insn "*negsf2_vfp"
311   [(set (match_operand:SF         0 "s_register_operand" "=w,?r")
312         (neg:SF (match_operand:SF 1 "s_register_operand" "w,r")))]
313   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
314   "@
315    fnegs%?\\t%0, %1
316    eor%?\\t%0, %1, #-2147483648"
317   [(set_attr "predicable" "yes")
318    (set_attr "type" "ffarith")]
321 (define_insn_and_split "*negdf2_vfp"
322   [(set (match_operand:DF         0 "s_register_operand" "=w,?r,?r")
323         (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
324   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
325   "@
326    fnegd%?\\t%P0, %P1
327    #
328    #"
329   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && reload_completed
330    && arm_general_register_operand (operands[0], DFmode)"
331   [(set (match_dup 0) (match_dup 1))]
332   "
333   if (REGNO (operands[0]) == REGNO (operands[1]))
334     {
335       operands[0] = gen_highpart (SImode, operands[0]);
336       operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
337     }
338   else
339     {
340       rtx in_hi, in_lo, out_hi, out_lo;
342       in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
343                            GEN_INT (0x80000000));
344       in_lo = gen_lowpart (SImode, operands[1]);
345       out_hi = gen_highpart (SImode, operands[0]);
346       out_lo = gen_lowpart (SImode, operands[0]);
348       if (REGNO (in_lo) == REGNO (out_hi))
349         {
350           emit_insn (gen_rtx_SET (SImode, out_lo, in_lo));
351           operands[0] = out_hi;
352           operands[1] = in_hi;
353         }
354       else
355         {
356           emit_insn (gen_rtx_SET (SImode, out_hi, in_hi));
357           operands[0] = out_lo;
358           operands[1] = in_lo;
359         }
360     }
361   "
362   [(set_attr "predicable" "yes")
363    (set_attr "length" "4,4,8")
364    (set_attr "type" "ffarith")]
368 ;; Arithmetic insns
370 (define_insn "*addsf3_vfp"
371   [(set (match_operand:SF          0 "s_register_operand" "=w")
372         (plus:SF (match_operand:SF 1 "s_register_operand" "w")
373                  (match_operand:SF 2 "s_register_operand" "w")))]
374   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
375   "fadds%?\\t%0, %1, %2"
376   [(set_attr "predicable" "yes")
377    (set_attr "type" "farith")]
380 (define_insn "*adddf3_vfp"
381   [(set (match_operand:DF          0 "s_register_operand" "=w")
382         (plus:DF (match_operand:DF 1 "s_register_operand" "w")
383                  (match_operand:DF 2 "s_register_operand" "w")))]
384   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
385   "faddd%?\\t%P0, %P1, %P2"
386   [(set_attr "predicable" "yes")
387    (set_attr "type" "farith")]
391 (define_insn "*subsf3_vfp"
392   [(set (match_operand:SF           0 "s_register_operand" "=w")
393         (minus:SF (match_operand:SF 1 "s_register_operand" "w")
394                   (match_operand:SF 2 "s_register_operand" "w")))]
395   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
396   "fsubs%?\\t%0, %1, %2"
397   [(set_attr "predicable" "yes")
398    (set_attr "type" "farith")]
401 (define_insn "*subdf3_vfp"
402   [(set (match_operand:DF           0 "s_register_operand" "=w")
403         (minus:DF (match_operand:DF 1 "s_register_operand" "w")
404                   (match_operand:DF 2 "s_register_operand" "w")))]
405   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
406   "fsubd%?\\t%P0, %P1, %P2"
407   [(set_attr "predicable" "yes")
408    (set_attr "type" "farith")]
412 ;; Division insns
414 (define_insn "*divsf3_vfp"
415   [(set (match_operand:SF         0 "s_register_operand" "+w")
416         (div:SF (match_operand:SF 1 "s_register_operand" "w")
417                 (match_operand:SF 2 "s_register_operand" "w")))]
418   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
419   "fdivs%?\\t%0, %1, %2"
420   [(set_attr "predicable" "yes")
421    (set_attr "type" "fdivs")]
424 (define_insn "*divdf3_vfp"
425   [(set (match_operand:DF         0 "s_register_operand" "+w")
426         (div:DF (match_operand:DF 1 "s_register_operand" "w")
427                 (match_operand:DF 2 "s_register_operand" "w")))]
428   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
429   "fdivd%?\\t%P0, %P1, %P2"
430   [(set_attr "predicable" "yes")
431    (set_attr "type" "fdivd")]
435 ;; Multiplication insns
437 (define_insn "*mulsf3_vfp"
438   [(set (match_operand:SF          0 "s_register_operand" "+w")
439         (mult:SF (match_operand:SF 1 "s_register_operand" "w")
440                  (match_operand:SF 2 "s_register_operand" "w")))]
441   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
442   "fmuls%?\\t%0, %1, %2"
443   [(set_attr "predicable" "yes")
444    (set_attr "type" "farith")]
447 (define_insn "*muldf3_vfp"
448   [(set (match_operand:DF          0 "s_register_operand" "+w")
449         (mult:DF (match_operand:DF 1 "s_register_operand" "w")
450                  (match_operand:DF 2 "s_register_operand" "w")))]
451   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
452   "fmuld%?\\t%P0, %P1, %P2"
453   [(set_attr "predicable" "yes")
454    (set_attr "type" "fmul")]
458 (define_insn "*mulsf3negsf_vfp"
459   [(set (match_operand:SF                  0 "s_register_operand" "+w")
460         (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "w"))
461                  (match_operand:SF         2 "s_register_operand" "w")))]
462   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
463   "fnmuls%?\\t%0, %1, %2"
464   [(set_attr "predicable" "yes")
465    (set_attr "type" "farith")]
468 (define_insn "*muldf3negdf_vfp"
469   [(set (match_operand:DF                  0 "s_register_operand" "+w")
470         (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
471                  (match_operand:DF         2 "s_register_operand" "w")))]
472   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
473   "fnmuld%?\\t%P0, %P1, %P2"
474   [(set_attr "predicable" "yes")
475    (set_attr "type" "fmul")]
479 ;; Multiply-accumulate insns
481 ;; 0 = 1 * 2 + 0
482 (define_insn "*mulsf3addsf_vfp"
483   [(set (match_operand:SF                   0 "s_register_operand" "=w")
484         (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
485                           (match_operand:SF 3 "s_register_operand" "w"))
486                  (match_operand:SF          1 "s_register_operand" "0")))]
487   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
488   "fmacs%?\\t%0, %2, %3"
489   [(set_attr "predicable" "yes")
490    (set_attr "type" "farith")]
493 (define_insn "*muldf3adddf_vfp"
494   [(set (match_operand:DF                   0 "s_register_operand" "=w")
495         (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
496                           (match_operand:DF 3 "s_register_operand" "w"))
497                  (match_operand:DF          1 "s_register_operand" "0")))]
498   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
499   "fmacd%?\\t%P0, %P2, %P3"
500   [(set_attr "predicable" "yes")
501    (set_attr "type" "fmul")]
504 ;; 0 = 1 * 2 - 0
505 (define_insn "*mulsf3subsf_vfp"
506   [(set (match_operand:SF                    0 "s_register_operand" "=w")
507         (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
508                            (match_operand:SF 3 "s_register_operand" "w"))
509                   (match_operand:SF          1 "s_register_operand" "0")))]
510   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
511   "fmscs%?\\t%0, %2, %3"
512   [(set_attr "predicable" "yes")
513    (set_attr "type" "farith")]
516 (define_insn "*muldf3subdf_vfp"
517   [(set (match_operand:DF                    0 "s_register_operand" "=w")
518         (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
519                            (match_operand:DF 3 "s_register_operand" "w"))
520                   (match_operand:DF          1 "s_register_operand" "0")))]
521   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
522   "fmscd%?\\t%P0, %P2, %P3"
523   [(set_attr "predicable" "yes")
524    (set_attr "type" "fmul")]
527 ;; 0 = -(1 * 2) + 0
528 (define_insn "*mulsf3negsfaddsf_vfp"
529   [(set (match_operand:SF                    0 "s_register_operand" "=w")
530         (minus:SF (match_operand:SF          1 "s_register_operand" "0")
531                   (mult:SF (match_operand:SF 2 "s_register_operand" "w")
532                            (match_operand:SF 3 "s_register_operand" "w"))))]
533   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
534   "fnmacs%?\\t%0, %2, %3"
535   [(set_attr "predicable" "yes")
536    (set_attr "type" "farith")]
539 (define_insn "*fmuldf3negdfadddf_vfp"
540   [(set (match_operand:DF                    0 "s_register_operand" "=w")
541         (minus:DF (match_operand:DF          1 "s_register_operand" "0")
542                   (mult:DF (match_operand:DF 2 "s_register_operand" "w")
543                            (match_operand:DF 3 "s_register_operand" "w"))))]
544   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
545   "fnmacd%?\\t%P0, %P2, %P3"
546   [(set_attr "predicable" "yes")
547    (set_attr "type" "fmul")]
551 ;; 0 = -(1 * 2) - 0
552 (define_insn "*mulsf3negsfsubsf_vfp"
553   [(set (match_operand:SF                     0 "s_register_operand" "=w")
554         (minus:SF (mult:SF
555                     (neg:SF (match_operand:SF 2 "s_register_operand" "w"))
556                     (match_operand:SF         3 "s_register_operand" "w"))
557                   (match_operand:SF           1 "s_register_operand" "0")))]
558   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
559   "fnmscs%?\\t%0, %2, %3"
560   [(set_attr "predicable" "yes")
561    (set_attr "type" "farith")]
564 (define_insn "*muldf3negdfsubdf_vfp"
565   [(set (match_operand:DF                     0 "s_register_operand" "=w")
566         (minus:DF (mult:DF
567                     (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
568                     (match_operand:DF         3 "s_register_operand" "w"))
569                   (match_operand:DF           1 "s_register_operand" "0")))]
570   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
571   "fnmscd%?\\t%P0, %P2, %P3"
572   [(set_attr "predicable" "yes")
573    (set_attr "type" "fmul")]
577 ;; Conversion routines
579 (define_insn "*extendsfdf2_vfp"
580   [(set (match_operand:DF                  0 "s_register_operand" "=w")
581         (float_extend:DF (match_operand:SF 1 "s_register_operand" "w")))]
582   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
583   "fcvtds%?\\t%P0, %1"
584   [(set_attr "predicable" "yes")
585    (set_attr "type" "f_cvt")]
588 (define_insn "*truncdfsf2_vfp"
589   [(set (match_operand:SF                  0 "s_register_operand" "=w")
590         (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
591   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
592   "fcvtsd%?\\t%0, %P1"
593   [(set_attr "predicable" "yes")
594    (set_attr "type" "f_cvt")]
597 (define_insn "*truncsisf2_vfp"
598   [(set (match_operand:SI                 0 "s_register_operand" "=w")
599         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
600   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
601   "ftosizs%?\\t%0, %1"
602   [(set_attr "predicable" "yes")
603    (set_attr "type" "f_cvt")]
606 (define_insn "*truncsidf2_vfp"
607   [(set (match_operand:SI                 0 "s_register_operand" "=w")
608         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
609   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
610   "ftosizd%?\\t%0, %P1"
611   [(set_attr "predicable" "yes")
612    (set_attr "type" "f_cvt")]
616 (define_insn "fixuns_truncsfsi2"
617   [(set (match_operand:SI                 0 "s_register_operand" "=w")
618         (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
619   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
620   "ftouizs%?\\t%0, %1"
621   [(set_attr "predicable" "yes")
622    (set_attr "type" "f_cvt")]
625 (define_insn "fixuns_truncdfsi2"
626   [(set (match_operand:SI                 0 "s_register_operand" "=w")
627         (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
628   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
629   "ftouizd%?\\t%0, %P1"
630   [(set_attr "predicable" "yes")
631    (set_attr "type" "f_cvt")]
635 (define_insn "*floatsisf2_vfp"
636   [(set (match_operand:SF           0 "s_register_operand" "=w")
637         (float:SF (match_operand:SI 1 "s_register_operand" "w")))]
638   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
639   "fsitos%?\\t%0, %1"
640   [(set_attr "predicable" "yes")
641    (set_attr "type" "f_cvt")]
644 (define_insn "*floatsidf2_vfp"
645   [(set (match_operand:DF           0 "s_register_operand" "=w")
646         (float:DF (match_operand:SI 1 "s_register_operand" "w")))]
647   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
648   "fsitod%?\\t%P0, %1"
649   [(set_attr "predicable" "yes")
650    (set_attr "type" "f_cvt")]
654 (define_insn "floatunssisf2"
655   [(set (match_operand:SF           0 "s_register_operand" "=w")
656         (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "w")))]
657   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
658   "fuitos%?\\t%0, %1"
659   [(set_attr "predicable" "yes")
660    (set_attr "type" "f_cvt")]
663 (define_insn "floatunssidf2"
664   [(set (match_operand:DF           0 "s_register_operand" "=w")
665         (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "w")))]
666   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
667   "fuitod%?\\t%P0, %1"
668   [(set_attr "predicable" "yes")
669    (set_attr "type" "f_cvt")]
673 ;; Sqrt insns.
675 (define_insn "*sqrtsf2_vfp"
676   [(set (match_operand:SF          0 "s_register_operand" "=w")
677         (sqrt:SF (match_operand:SF 1 "s_register_operand" "w")))]
678   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
679   "fsqrts%?\\t%0, %1"
680   [(set_attr "predicable" "yes")
681    (set_attr "type" "fdivs")]
684 (define_insn "*sqrtdf2_vfp"
685   [(set (match_operand:DF          0 "s_register_operand" "=w")
686         (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
687   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
688   "fsqrtd%?\\t%P0, %P1"
689   [(set_attr "predicable" "yes")
690    (set_attr "type" "fdivd")]
694 ;; Patterns to split/copy vfp condition flags.
696 (define_insn "*movcc_vfp"
697   [(set (reg CC_REGNUM)
698         (reg VFPCC_REGNUM))]
699   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
700   "fmstat%?"
701   [(set_attr "conds" "set")
702    (set_attr "type" "f_flag")]
705 (define_insn_and_split "*cmpsf_split_vfp"
706   [(set (reg:CCFP CC_REGNUM)
707         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w")
708                       (match_operand:SF 1 "vfp_compare_operand" "wG")))]
709   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
710   "#"
711   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
712   [(set (reg:CCFP VFPCC_REGNUM)
713         (compare:CCFP (match_dup 0)
714                       (match_dup 1)))
715    (set (reg:CCFP CC_REGNUM)
716         (reg:CCFP VFPCC_REGNUM))]
717   ""
720 (define_insn_and_split "*cmpsf_trap_split_vfp"
721   [(set (reg:CCFPE CC_REGNUM)
722         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w")
723                        (match_operand:SF 1 "vfp_compare_operand" "wG")))]
724   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
725   "#"
726   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
727   [(set (reg:CCFPE VFPCC_REGNUM)
728         (compare:CCFPE (match_dup 0)
729                        (match_dup 1)))
730    (set (reg:CCFPE CC_REGNUM)
731         (reg:CCFPE VFPCC_REGNUM))]
732   ""
735 (define_insn_and_split "*cmpdf_split_vfp"
736   [(set (reg:CCFP CC_REGNUM)
737         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w")
738                       (match_operand:DF 1 "vfp_compare_operand" "wG")))]
739   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
740   "#"
741   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
742   [(set (reg:CCFP VFPCC_REGNUM)
743         (compare:CCFP (match_dup 0)
744                        (match_dup 1)))
745    (set (reg:CCFP CC_REGNUM)
746         (reg:CCFPE VFPCC_REGNUM))]
747   ""
750 (define_insn_and_split "*cmpdf_trap_split_vfp"
751   [(set (reg:CCFPE CC_REGNUM)
752         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w")
753                        (match_operand:DF 1 "vfp_compare_operand" "wG")))]
754   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
755   "#"
756   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
757   [(set (reg:CCFPE VFPCC_REGNUM)
758         (compare:CCFPE (match_dup 0)
759                        (match_dup 1)))
760    (set (reg:CCFPE CC_REGNUM)
761         (reg:CCFPE VFPCC_REGNUM))]
762   ""
766 ;; Comparison patterns
768 (define_insn "*cmpsf_vfp"
769   [(set (reg:CCFP VFPCC_REGNUM)
770         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w,w")
771                       (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
772   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
773   "@
774    fcmps%?\\t%0, %1
775    fcmpzs%?\\t%0"
776   [(set_attr "predicable" "yes")
777    (set_attr "type" "ffarith")]
780 (define_insn "*cmpsf_trap_vfp"
781   [(set (reg:CCFPE VFPCC_REGNUM)
782         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w,w")
783                        (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
784   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
785   "@
786    fcmpes%?\\t%0, %1
787    fcmpezs%?\\t%0"
788   [(set_attr "predicable" "yes")
789    (set_attr "type" "ffarith")]
792 (define_insn "*cmpdf_vfp"
793   [(set (reg:CCFP VFPCC_REGNUM)
794         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w,w")
795                       (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
796   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
797   "@
798    fcmpd%?\\t%P0, %P1
799    fcmpzd%?\\t%P0"
800   [(set_attr "predicable" "yes")
801    (set_attr "type" "ffarith")]
804 (define_insn "*cmpdf_trap_vfp"
805   [(set (reg:CCFPE VFPCC_REGNUM)
806         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w,w")
807                        (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
808   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
809   "@
810    fcmped%?\\t%P0, %P1
811    fcmpezd%?\\t%P0"
812   [(set_attr "predicable" "yes")
813    (set_attr "type" "ffarith")]
817 ;; Store multiple insn used in function prologue.
819 (define_insn "*push_multi_vfp"
820   [(match_parallel 2 "multi_register_push"
821     [(set (match_operand:BLK 0 "memory_operand" "=m")
822           (unspec:BLK [(match_operand:DF 1 "s_register_operand" "w")]
823                       UNSPEC_PUSH_MULT))])]
824   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
825   "* return vfp_output_fstmx (operands);"
826   [(set_attr "type" "f_stored")]
830 ;; Unimplemented insns:
831 ;; fldm*
832 ;; fstm*
833 ;; fmdhr et al (VFPv1)
834 ;; Support for xD (single precision only) variants.
835 ;; fmrrs, fmsrr