OSDN Git Service

Merge from csl-arm-branch.
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / vfp.md
1 ;; ARM VFP coprocessor Machine Description
2 ;; Copyright (C) 2003 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.
11 ;;
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.
16 ;;
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.  */
21
22 ;; Additional register numbers
23 (define_constants
24   [(VFPCC_REGNUM 95)]
25 )
26
27 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28 ;; Pipeline description
29 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30
31 (define_automaton "vfp11")
32
33 ;; There are 3 pipelines in the VFP11 unit.
34 ;;
35 ;; - A 8-stage FMAC pipeline (7 execute + writeback) with forward from
36 ;;   fourth stage for simple operations.
37 ;;
38 ;; - A 5-stage DS pipeline (4 execute + writeback) for divide/sqrt insns.
39 ;;   These insns also uses first execute stage of FMAC pipeline.
40 ;;
41 ;; - A 4-stage LS pipeline (execute + 2 memory + writeback) with forward from
42 ;;   second memory stage for loads.
43
44 ;; We do not model Write-After-Read hazards.
45 ;; We do not do write scheduling with the arm core, so it is only neccessary
46 ;; to model the first stage of each pieline
47 ;; ??? Need to model LS pipeline properly for load/store multiple?
48 ;; We do not model fmstat properly.  This could be done by modeiling pipelines
49 ;; properly and defining an absence set between a dummy fmstat unit and all
50 ;; other vfp units.
51
52 (define_cpu_unit "fmac" "vfp11")
53
54 (define_cpu_unit "ds" "vfp11")
55
56 (define_cpu_unit "vfp_ls" "vfp11")
57
58 ;; The VFP "type" attributes differ from those used in the FPA model.
59 ;; ffarith      Fast floating point insns, eg. abs, neg, cpy, cmp.
60 ;; farith       Most arithmetic insns.
61 ;; fmul         Double preision 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.
68
69 (define_insn_reservation "vfp_ffarith" 4
70  (and (eq_attr "fpu" "vfp")
71       (eq_attr "type" "ffarith"))
72  "fmac")
73
74 (define_insn_reservation "vfp_farith" 8
75  (and (eq_attr "fpu" "vfp")
76       (eq_attr "type" "farith"))
77  "fmac")
78
79 (define_insn_reservation "vfp_fmul" 9
80  (and (eq_attr "fpu" "vfp")
81       (eq_attr "type" "fmul"))
82  "fmac*2")
83
84 (define_insn_reservation "vfp_fdivs" 19
85  (and (eq_attr "fpu" "vfp")
86       (eq_attr "type" "fdivs"))
87  "ds*15")
88
89 (define_insn_reservation "vfp_fdivd" 33
90  (and (eq_attr "fpu" "vfp")
91       (eq_attr "type" "fdivd"))
92  "fmac+ds*29")
93
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")
99
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")
104
105
106 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
107 ;; Insn pattersn
108 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
109
110 ;; SImode moves
111 ;; ??? For now do not allow loading constants into vfp regs.  This causes
112 ;; problems because small sonstants 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, U")
115       (match_operand:SI 1 "general_operand"        "rI,K,mi,r,r,!w,!w,Ui,!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,*")]
133 )
134
135
136 ;; DImode moves
137
138 (define_insn "*arm_movdi_vfp"
139   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,o<>,w,r,w,w ,U")
140         (match_operand:DI 1 "di_operand"              "rIK,mi,r ,r,w,w,Ui,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,*")]
165 )
166
167
168 ;; SFmode moves
169
170 (define_insn "*movsf_vfp"
171   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,r,w ,U,r ,m,w,r")
172         (match_operand:SF 1 "general_operand"      " r,w,UE,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,*,*,*")]
189 )
190
191
192 ;; DFmode moves
193
194 (define_insn "*movdf_vfp"
195   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,r,r, m,w ,U,w,r")
196         (match_operand:DF 1 "soft_df_operand"              " r,w,mF,r,UF,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,*,*,*")]
223 )
224
225
226 ;; Conditional move patterns
227
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")]
249 )
250
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")]
272 )
273
274
275 ;; Sign manipulation functions
276
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")]
284 )
285
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")]
293 )
294
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")]
302 )
303
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")]
311 )
312
313
314 ;; Arithmetic insns
315
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")]
324 )
325
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")]
334 )
335
336
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")]
345 )
346
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")]
355 )
356
357
358 ;; Division insns
359
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")]
368 )
369
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")]
378 )
379
380
381 ;; Multiplication insns
382
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")]
391 )
392
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")]
401 )
402
403
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")]
412 )
413
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")]
422 )
423
424
425 ;; Multiply-accumulate insns
426
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")]
437 )
438
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")]
448 )
449
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")]
460 )
461
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")]
471 )
472
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")]
483 )
484
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")]
494 )
495
496
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")]
508 )
509
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")]
520 )
521
522
523 ;; Conversion routines
524
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")]
532 )
533
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")]
541 )
542
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")]
550 )
551
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")]
559 )
560
561 (define_insn "*floatsisf2_vfp"
562   [(set (match_operand:SF           0 "s_register_operand" "=w")
563         (float:SF (match_operand:SI 1 "s_register_operand" "w")))]
564   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
565   "fsitos%?\\t%0, %1"
566   [(set_attr "predicable" "yes")
567    (set_attr "type" "farith")]
568 )
569
570 (define_insn "*floatsidf2_vfp"
571   [(set (match_operand:DF           0 "s_register_operand" "=w")
572         (float:DF (match_operand:SI 1 "s_register_operand" "w")))]
573   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
574   "fsitod%?\\t%P0, %1"
575   [(set_attr "predicable" "yes")
576    (set_attr "type" "farith")]
577 )
578
579
580 ;; Sqrt insns.
581
582 (define_insn "*sqrtsf2_vfp"
583   [(set (match_operand:SF          0 "s_register_operand" "=w")
584         (sqrt:SF (match_operand:SF 1 "s_register_operand" "w")))]
585   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
586   "fsqrts%?\\t%0, %1"
587   [(set_attr "predicable" "yes")
588    (set_attr "type" "fdivs")]
589 )
590
591 (define_insn "*sqrtdf2_vfp"
592   [(set (match_operand:DF          0 "s_register_operand" "=w")
593         (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
594   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
595   "fsqrtd%?\\t%P0, %P1"
596   [(set_attr "predicable" "yes")
597    (set_attr "type" "fdivd")]
598 )
599
600
601 ;; Patterns to split/copy vfp condition flags.
602
603 (define_insn "*movcc_vfp"
604   [(set (reg CC_REGNUM)
605         (reg VFPCC_REGNUM))]
606   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
607   "fmstat%?"
608   [(set_attr "conds" "set")
609    (set_attr "type" "ffarith")]
610 )
611
612 (define_insn_and_split "*cmpsf_split_vfp"
613   [(set (reg:CCFP CC_REGNUM)
614         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w")
615                       (match_operand:SF 1 "vfp_compare_operand" "wG")))]
616   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
617   "#"
618   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
619   [(set (reg:CCFP VFPCC_REGNUM)
620         (compare:CCFP (match_dup 0)
621                       (match_dup 1)))
622    (set (reg:CCFP CC_REGNUM)
623         (reg:CCFP VFPCC_REGNUM))]
624   ""
625 )
626
627 (define_insn_and_split "*cmpsf_trap_split_vfp"
628   [(set (reg:CCFPE CC_REGNUM)
629         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w")
630                        (match_operand:SF 1 "vfp_compare_operand" "wG")))]
631   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
632   "#"
633   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
634   [(set (reg:CCFPE VFPCC_REGNUM)
635         (compare:CCFPE (match_dup 0)
636                        (match_dup 1)))
637    (set (reg:CCFPE CC_REGNUM)
638         (reg:CCFPE VFPCC_REGNUM))]
639   ""
640 )
641
642 (define_insn_and_split "*cmpdf_split_vfp"
643   [(set (reg:CCFP CC_REGNUM)
644         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w")
645                       (match_operand:DF 1 "vfp_compare_operand" "wG")))]
646   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
647   "#"
648   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
649   [(set (reg:CCFP VFPCC_REGNUM)
650         (compare:CCFP (match_dup 0)
651                        (match_dup 1)))
652    (set (reg:CCFP CC_REGNUM)
653         (reg:CCFPE VFPCC_REGNUM))]
654   ""
655 )
656
657 (define_insn_and_split "*cmpdf_trap_split_vfp"
658   [(set (reg:CCFPE CC_REGNUM)
659         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w")
660                        (match_operand:DF 1 "vfp_compare_operand" "wG")))]
661   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
662   "#"
663   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
664   [(set (reg:CCFPE VFPCC_REGNUM)
665         (compare:CCFPE (match_dup 0)
666                        (match_dup 1)))
667    (set (reg:CCFPE CC_REGNUM)
668         (reg:CCFPE VFPCC_REGNUM))]
669   ""
670 )
671
672
673 ;; Comparison patterns
674
675 (define_insn "*cmpsf_vfp"
676   [(set (reg:CCFP VFPCC_REGNUM)
677         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w,w")
678                       (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
679   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
680   "@
681    fcmps%?\\t%0, %1
682    fcmpzs%?\\t%0"
683   [(set_attr "predicable" "yes")
684    (set_attr "type" "ffarith")]
685 )
686
687 (define_insn "*cmpsf_trap_vfp"
688   [(set (reg:CCFPE VFPCC_REGNUM)
689         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w,w")
690                        (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
691   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
692   "@
693    fcmpes%?\\t%0, %1
694    fcmpezs%?\\t%0"
695   [(set_attr "predicable" "yes")
696    (set_attr "type" "ffarith")]
697 )
698
699 (define_insn "*cmpdf_vfp"
700   [(set (reg:CCFP VFPCC_REGNUM)
701         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w,w")
702                       (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
703   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
704   "@
705    fcmpd%?\\t%P0, %P1
706    fcmpzd%?\\t%P0"
707   [(set_attr "predicable" "yes")
708    (set_attr "type" "ffarith")]
709 )
710
711 (define_insn "*cmpdf_trap_vfp"
712   [(set (reg:CCFPE VFPCC_REGNUM)
713         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w,w")
714                        (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
715   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
716   "@
717    fcmped%?\\t%P0, %P1
718    fcmpezd%?\\t%P0"
719   [(set_attr "predicable" "yes")
720    (set_attr "type" "ffarith")]
721 )
722
723
724 ;; Store multiple insn used in function prologue.
725
726 (define_insn "*push_multi_vfp"
727   [(match_parallel 2 "multi_register_push"
728     [(set (match_operand:BLK 0 "memory_operand" "=m")
729           (unspec:BLK [(match_operand:DF 1 "s_register_operand" "w")]
730                       UNSPEC_PUSH_MULT))])]
731   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
732   "* return vfp_output_fstmx (operands);"
733   [(set_attr "type" "f_store")]
734 )
735
736
737 ;; Unimplemented insns:
738 ;; fldm*
739 ;; fstm*
740 ;; fmdhr et al (VFPv1)
741 ;; Support for xD (single precisio only) variants.
742 ;; fmrrs, fmsrr
743 ;; fuito*
744 ;; ftoui*