]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/gcc/config/arm/vfp.md
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / gcc / config / arm / vfp.md
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.
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, 51 Franklin Street, Fifth Floor, Boston, MA
20 ;; 02110-1301, 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 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.
51
52 (define_cpu_unit "fmac" "vfp11")
53
54 (define_cpu_unit "ds" "vfp11")
55
56 (define_cpu_unit "vfp_ls" "vfp11")
57
58 (define_cpu_unit "fmstat" "vfp11")
59
60 (exclusion_set "fmac,ds" "fmstat")
61
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
74
75 (define_insn_reservation "vfp_ffarith" 4
76  (and (eq_attr "generic_vfp" "yes")
77       (eq_attr "type" "ffarith"))
78  "fmac")
79
80 (define_insn_reservation "vfp_farith" 8
81  (and (eq_attr "generic_vfp" "yes")
82       (eq_attr "type" "farith,f_cvt"))
83  "fmac")
84
85 (define_insn_reservation "vfp_fmul" 9
86  (and (eq_attr "generic_vfp" "yes")
87       (eq_attr "type" "fmul"))
88  "fmac*2")
89
90 (define_insn_reservation "vfp_fdivs" 19
91  (and (eq_attr "generic_vfp" "yes")
92       (eq_attr "type" "fdivs"))
93  "ds*15")
94
95 (define_insn_reservation "vfp_fdivd" 33
96  (and (eq_attr "generic_vfp" "yes")
97       (eq_attr "type" "fdivd"))
98  "fmac+ds*29")
99
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")
105
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")
110
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")
115
116 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
117 ;; Insn pattern
118 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
119
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,*")]
143 )
144
145
146 ;; DImode moves
147
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, %Q1, %R1\\t%@ int\";
164     case 4:
165       return \"fmrrd%?\\t%Q0, %R0, %P1\\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,*")]
180 )
181
182
183 ;; SFmode moves
184 ;; Disparage the w<->r cases because reloading an invalid address is
185 ;; preferable to loading the value via integer registers.
186
187 (define_insn "*movsf_vfp"
188   [(set (match_operand:SF 0 "nonimmediate_operand" "=w,?r,w  ,Uv,r ,m,w,r")
189         (match_operand:SF 1 "general_operand"      " ?r,w,UvE,w, mE,r,w,r"))]
190   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
191    && (   s_register_operand (operands[0], SFmode)
192        || s_register_operand (operands[1], SFmode))"
193   "@
194   fmsr%?\\t%0, %1
195   fmrs%?\\t%0, %1
196   flds%?\\t%0, %1
197   fsts%?\\t%1, %0
198   ldr%?\\t%0, %1\\t%@ float
199   str%?\\t%1, %0\\t%@ float
200   fcpys%?\\t%0, %1
201   mov%?\\t%0, %1\\t%@ float"
202   [(set_attr "predicable" "yes")
203    (set_attr "type" "r_2_f,f_2_r,ffarith,*,f_loads,f_stores,load1,store1")
204    (set_attr "pool_range" "*,*,1020,*,4096,*,*,*")
205    (set_attr "neg_pool_range" "*,*,1008,*,4080,*,*,*")]
206 )
207
208
209 ;; DFmode moves
210
211 (define_insn "*movdf_vfp"
212   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,r, m,w  ,Uv,w,r")
213         (match_operand:DF 1 "soft_df_operand"              " ?r,w,mF,r,UvF,w, w,r"))]
214   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
215    && (   register_operand (operands[0], DFmode)
216        || register_operand (operands[1], DFmode))"
217   "*
218   {
219     switch (which_alternative)
220       {
221       case 0:
222         return \"fmdrr%?\\t%P0, %Q1, %R1\";
223       case 1:
224         return \"fmrrd%?\\t%Q0, %R0, %P1\";
225       case 2: case 3:
226         return output_move_double (operands);
227       case 4:
228         return \"fldd%?\\t%P0, %1\";
229       case 5:
230         return \"fstd%?\\t%P1, %0\";
231       case 6:
232         return \"fcpyd%?\\t%P0, %P1\";
233       case 7:
234         return \"#\";
235       default:
236         gcc_unreachable ();
237       }
238     }
239   "
240   [(set_attr "type" "r_2_f,f_2_r,ffarith,*,load2,store2,f_loadd,f_stored")
241    (set_attr "length" "4,4,8,8,4,4,4,8")
242    (set_attr "pool_range" "*,*,1020,*,1020,*,*,*")
243    (set_attr "neg_pool_range" "*,*,1008,*,1008,*,*,*")]
244 )
245
246
247 ;; Conditional move patterns
248
249 (define_insn "*movsfcc_vfp"
250   [(set (match_operand:SF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
251         (if_then_else:SF
252           (match_operator   3 "arm_comparison_operator"
253             [(match_operand 4 "cc_register" "") (const_int 0)])
254           (match_operand:SF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
255           (match_operand:SF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
256   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
257   "@
258    fcpys%D3\\t%0, %2
259    fcpys%d3\\t%0, %1
260    fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
261    fmsr%D3\\t%0, %2
262    fmsr%d3\\t%0, %1
263    fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
264    fmrs%D3\\t%0, %2
265    fmrs%d3\\t%0, %1
266    fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
267    [(set_attr "conds" "use")
268     (set_attr "length" "4,4,8,4,4,8,4,4,8")
269     (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 )
271
272 (define_insn "*movdfcc_vfp"
273   [(set (match_operand:DF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
274         (if_then_else:DF
275           (match_operator   3 "arm_comparison_operator"
276             [(match_operand 4 "cc_register" "") (const_int 0)])
277           (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
278           (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
279   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
280   "@
281    fcpyd%D3\\t%P0, %P2
282    fcpyd%d3\\t%P0, %P1
283    fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
284    fmdrr%D3\\t%P0, %Q2, %R2
285    fmdrr%d3\\t%P0, %Q1, %R1
286    fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
287    fmrrd%D3\\t%Q0, %R0, %P2
288    fmrrd%d3\\t%Q0, %R0, %P1
289    fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
290    [(set_attr "conds" "use")
291     (set_attr "length" "4,4,8,4,4,8,4,4,8")
292     (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
293 )
294
295
296 ;; Sign manipulation functions
297
298 (define_insn "*abssf2_vfp"
299   [(set (match_operand:SF         0 "s_register_operand" "=w")
300         (abs:SF (match_operand:SF 1 "s_register_operand" "w")))]
301   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
302   "fabss%?\\t%0, %1"
303   [(set_attr "predicable" "yes")
304    (set_attr "type" "ffarith")]
305 )
306
307 (define_insn "*absdf2_vfp"
308   [(set (match_operand:DF         0 "s_register_operand" "=w")
309         (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
310   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
311   "fabsd%?\\t%P0, %P1"
312   [(set_attr "predicable" "yes")
313    (set_attr "type" "ffarith")]
314 )
315
316 (define_insn "*negsf2_vfp"
317   [(set (match_operand:SF         0 "s_register_operand" "=w,?r")
318         (neg:SF (match_operand:SF 1 "s_register_operand" "w,r")))]
319   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
320   "@
321    fnegs%?\\t%0, %1
322    eor%?\\t%0, %1, #-2147483648"
323   [(set_attr "predicable" "yes")
324    (set_attr "type" "ffarith")]
325 )
326
327 (define_insn_and_split "*negdf2_vfp"
328   [(set (match_operand:DF         0 "s_register_operand" "=w,?r,?r")
329         (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
330   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
331   "@
332    fnegd%?\\t%P0, %P1
333    #
334    #"
335   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && reload_completed
336    && arm_general_register_operand (operands[0], DFmode)"
337   [(set (match_dup 0) (match_dup 1))]
338   "
339   if (REGNO (operands[0]) == REGNO (operands[1]))
340     {
341       operands[0] = gen_highpart (SImode, operands[0]);
342       operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
343     }
344   else
345     {
346       rtx in_hi, in_lo, out_hi, out_lo;
347
348       in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
349                            GEN_INT (0x80000000));
350       in_lo = gen_lowpart (SImode, operands[1]);
351       out_hi = gen_highpart (SImode, operands[0]);
352       out_lo = gen_lowpart (SImode, operands[0]);
353
354       if (REGNO (in_lo) == REGNO (out_hi))
355         {
356           emit_insn (gen_rtx_SET (SImode, out_lo, in_lo));
357           operands[0] = out_hi;
358           operands[1] = in_hi;
359         }
360       else
361         {
362           emit_insn (gen_rtx_SET (SImode, out_hi, in_hi));
363           operands[0] = out_lo;
364           operands[1] = in_lo;
365         }
366     }
367   "
368   [(set_attr "predicable" "yes")
369    (set_attr "length" "4,4,8")
370    (set_attr "type" "ffarith")]
371 )
372
373
374 ;; Arithmetic insns
375
376 (define_insn "*addsf3_vfp"
377   [(set (match_operand:SF          0 "s_register_operand" "=w")
378         (plus:SF (match_operand:SF 1 "s_register_operand" "w")
379                  (match_operand:SF 2 "s_register_operand" "w")))]
380   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
381   "fadds%?\\t%0, %1, %2"
382   [(set_attr "predicable" "yes")
383    (set_attr "type" "farith")]
384 )
385
386 (define_insn "*adddf3_vfp"
387   [(set (match_operand:DF          0 "s_register_operand" "=w")
388         (plus:DF (match_operand:DF 1 "s_register_operand" "w")
389                  (match_operand:DF 2 "s_register_operand" "w")))]
390   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
391   "faddd%?\\t%P0, %P1, %P2"
392   [(set_attr "predicable" "yes")
393    (set_attr "type" "farith")]
394 )
395
396
397 (define_insn "*subsf3_vfp"
398   [(set (match_operand:SF           0 "s_register_operand" "=w")
399         (minus:SF (match_operand:SF 1 "s_register_operand" "w")
400                   (match_operand:SF 2 "s_register_operand" "w")))]
401   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
402   "fsubs%?\\t%0, %1, %2"
403   [(set_attr "predicable" "yes")
404    (set_attr "type" "farith")]
405 )
406
407 (define_insn "*subdf3_vfp"
408   [(set (match_operand:DF           0 "s_register_operand" "=w")
409         (minus:DF (match_operand:DF 1 "s_register_operand" "w")
410                   (match_operand:DF 2 "s_register_operand" "w")))]
411   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
412   "fsubd%?\\t%P0, %P1, %P2"
413   [(set_attr "predicable" "yes")
414    (set_attr "type" "farith")]
415 )
416
417
418 ;; Division insns
419
420 (define_insn "*divsf3_vfp"
421   [(set (match_operand:SF         0 "s_register_operand" "+w")
422         (div:SF (match_operand:SF 1 "s_register_operand" "w")
423                 (match_operand:SF 2 "s_register_operand" "w")))]
424   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
425   "fdivs%?\\t%0, %1, %2"
426   [(set_attr "predicable" "yes")
427    (set_attr "type" "fdivs")]
428 )
429
430 (define_insn "*divdf3_vfp"
431   [(set (match_operand:DF         0 "s_register_operand" "+w")
432         (div:DF (match_operand:DF 1 "s_register_operand" "w")
433                 (match_operand:DF 2 "s_register_operand" "w")))]
434   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
435   "fdivd%?\\t%P0, %P1, %P2"
436   [(set_attr "predicable" "yes")
437    (set_attr "type" "fdivd")]
438 )
439
440
441 ;; Multiplication insns
442
443 (define_insn "*mulsf3_vfp"
444   [(set (match_operand:SF          0 "s_register_operand" "+w")
445         (mult:SF (match_operand:SF 1 "s_register_operand" "w")
446                  (match_operand:SF 2 "s_register_operand" "w")))]
447   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
448   "fmuls%?\\t%0, %1, %2"
449   [(set_attr "predicable" "yes")
450    (set_attr "type" "farith")]
451 )
452
453 (define_insn "*muldf3_vfp"
454   [(set (match_operand:DF          0 "s_register_operand" "+w")
455         (mult:DF (match_operand:DF 1 "s_register_operand" "w")
456                  (match_operand:DF 2 "s_register_operand" "w")))]
457   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
458   "fmuld%?\\t%P0, %P1, %P2"
459   [(set_attr "predicable" "yes")
460    (set_attr "type" "fmul")]
461 )
462
463
464 (define_insn "*mulsf3negsf_vfp"
465   [(set (match_operand:SF                  0 "s_register_operand" "+w")
466         (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "w"))
467                  (match_operand:SF         2 "s_register_operand" "w")))]
468   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
469   "fnmuls%?\\t%0, %1, %2"
470   [(set_attr "predicable" "yes")
471    (set_attr "type" "farith")]
472 )
473
474 (define_insn "*muldf3negdf_vfp"
475   [(set (match_operand:DF                  0 "s_register_operand" "+w")
476         (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
477                  (match_operand:DF         2 "s_register_operand" "w")))]
478   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
479   "fnmuld%?\\t%P0, %P1, %P2"
480   [(set_attr "predicable" "yes")
481    (set_attr "type" "fmul")]
482 )
483
484
485 ;; Multiply-accumulate insns
486
487 ;; 0 = 1 * 2 + 0
488 (define_insn "*mulsf3addsf_vfp"
489   [(set (match_operand:SF                   0 "s_register_operand" "=w")
490         (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
491                           (match_operand:SF 3 "s_register_operand" "w"))
492                  (match_operand:SF          1 "s_register_operand" "0")))]
493   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
494   "fmacs%?\\t%0, %2, %3"
495   [(set_attr "predicable" "yes")
496    (set_attr "type" "farith")]
497 )
498
499 (define_insn "*muldf3adddf_vfp"
500   [(set (match_operand:DF                   0 "s_register_operand" "=w")
501         (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
502                           (match_operand:DF 3 "s_register_operand" "w"))
503                  (match_operand:DF          1 "s_register_operand" "0")))]
504   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
505   "fmacd%?\\t%P0, %P2, %P3"
506   [(set_attr "predicable" "yes")
507    (set_attr "type" "fmul")]
508 )
509
510 ;; 0 = 1 * 2 - 0
511 (define_insn "*mulsf3subsf_vfp"
512   [(set (match_operand:SF                    0 "s_register_operand" "=w")
513         (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
514                            (match_operand:SF 3 "s_register_operand" "w"))
515                   (match_operand:SF          1 "s_register_operand" "0")))]
516   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
517   "fmscs%?\\t%0, %2, %3"
518   [(set_attr "predicable" "yes")
519    (set_attr "type" "farith")]
520 )
521
522 (define_insn "*muldf3subdf_vfp"
523   [(set (match_operand:DF                    0 "s_register_operand" "=w")
524         (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
525                            (match_operand:DF 3 "s_register_operand" "w"))
526                   (match_operand:DF          1 "s_register_operand" "0")))]
527   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
528   "fmscd%?\\t%P0, %P2, %P3"
529   [(set_attr "predicable" "yes")
530    (set_attr "type" "fmul")]
531 )
532
533 ;; 0 = -(1 * 2) + 0
534 (define_insn "*mulsf3negsfaddsf_vfp"
535   [(set (match_operand:SF                    0 "s_register_operand" "=w")
536         (minus:SF (match_operand:SF          1 "s_register_operand" "0")
537                   (mult:SF (match_operand:SF 2 "s_register_operand" "w")
538                            (match_operand:SF 3 "s_register_operand" "w"))))]
539   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
540   "fnmacs%?\\t%0, %2, %3"
541   [(set_attr "predicable" "yes")
542    (set_attr "type" "farith")]
543 )
544
545 (define_insn "*fmuldf3negdfadddf_vfp"
546   [(set (match_operand:DF                    0 "s_register_operand" "=w")
547         (minus:DF (match_operand:DF          1 "s_register_operand" "0")
548                   (mult:DF (match_operand:DF 2 "s_register_operand" "w")
549                            (match_operand:DF 3 "s_register_operand" "w"))))]
550   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
551   "fnmacd%?\\t%P0, %P2, %P3"
552   [(set_attr "predicable" "yes")
553    (set_attr "type" "fmul")]
554 )
555
556
557 ;; 0 = -(1 * 2) - 0
558 (define_insn "*mulsf3negsfsubsf_vfp"
559   [(set (match_operand:SF                     0 "s_register_operand" "=w")
560         (minus:SF (mult:SF
561                     (neg:SF (match_operand:SF 2 "s_register_operand" "w"))
562                     (match_operand:SF         3 "s_register_operand" "w"))
563                   (match_operand:SF           1 "s_register_operand" "0")))]
564   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
565   "fnmscs%?\\t%0, %2, %3"
566   [(set_attr "predicable" "yes")
567    (set_attr "type" "farith")]
568 )
569
570 (define_insn "*muldf3negdfsubdf_vfp"
571   [(set (match_operand:DF                     0 "s_register_operand" "=w")
572         (minus:DF (mult:DF
573                     (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
574                     (match_operand:DF         3 "s_register_operand" "w"))
575                   (match_operand:DF           1 "s_register_operand" "0")))]
576   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
577   "fnmscd%?\\t%P0, %P2, %P3"
578   [(set_attr "predicable" "yes")
579    (set_attr "type" "fmul")]
580 )
581
582
583 ;; Conversion routines
584
585 (define_insn "*extendsfdf2_vfp"
586   [(set (match_operand:DF                  0 "s_register_operand" "=w")
587         (float_extend:DF (match_operand:SF 1 "s_register_operand" "w")))]
588   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
589   "fcvtds%?\\t%P0, %1"
590   [(set_attr "predicable" "yes")
591    (set_attr "type" "f_cvt")]
592 )
593
594 (define_insn "*truncdfsf2_vfp"
595   [(set (match_operand:SF                  0 "s_register_operand" "=w")
596         (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
597   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
598   "fcvtsd%?\\t%0, %P1"
599   [(set_attr "predicable" "yes")
600    (set_attr "type" "f_cvt")]
601 )
602
603 (define_insn "*truncsisf2_vfp"
604   [(set (match_operand:SI                 0 "s_register_operand" "=w")
605         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
606   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
607   "ftosizs%?\\t%0, %1"
608   [(set_attr "predicable" "yes")
609    (set_attr "type" "f_cvt")]
610 )
611
612 (define_insn "*truncsidf2_vfp"
613   [(set (match_operand:SI                 0 "s_register_operand" "=w")
614         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
615   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
616   "ftosizd%?\\t%0, %P1"
617   [(set_attr "predicable" "yes")
618    (set_attr "type" "f_cvt")]
619 )
620
621
622 (define_insn "fixuns_truncsfsi2"
623   [(set (match_operand:SI                 0 "s_register_operand" "=w")
624         (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
625   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
626   "ftouizs%?\\t%0, %1"
627   [(set_attr "predicable" "yes")
628    (set_attr "type" "f_cvt")]
629 )
630
631 (define_insn "fixuns_truncdfsi2"
632   [(set (match_operand:SI                 0 "s_register_operand" "=w")
633         (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
634   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
635   "ftouizd%?\\t%0, %P1"
636   [(set_attr "predicable" "yes")
637    (set_attr "type" "f_cvt")]
638 )
639
640
641 (define_insn "*floatsisf2_vfp"
642   [(set (match_operand:SF           0 "s_register_operand" "=w")
643         (float:SF (match_operand:SI 1 "s_register_operand" "w")))]
644   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
645   "fsitos%?\\t%0, %1"
646   [(set_attr "predicable" "yes")
647    (set_attr "type" "f_cvt")]
648 )
649
650 (define_insn "*floatsidf2_vfp"
651   [(set (match_operand:DF           0 "s_register_operand" "=w")
652         (float:DF (match_operand:SI 1 "s_register_operand" "w")))]
653   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
654   "fsitod%?\\t%P0, %1"
655   [(set_attr "predicable" "yes")
656    (set_attr "type" "f_cvt")]
657 )
658
659
660 (define_insn "floatunssisf2"
661   [(set (match_operand:SF           0 "s_register_operand" "=w")
662         (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "w")))]
663   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
664   "fuitos%?\\t%0, %1"
665   [(set_attr "predicable" "yes")
666    (set_attr "type" "f_cvt")]
667 )
668
669 (define_insn "floatunssidf2"
670   [(set (match_operand:DF           0 "s_register_operand" "=w")
671         (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "w")))]
672   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
673   "fuitod%?\\t%P0, %1"
674   [(set_attr "predicable" "yes")
675    (set_attr "type" "f_cvt")]
676 )
677
678
679 ;; Sqrt insns.
680
681 (define_insn "*sqrtsf2_vfp"
682   [(set (match_operand:SF          0 "s_register_operand" "=w")
683         (sqrt:SF (match_operand:SF 1 "s_register_operand" "w")))]
684   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
685   "fsqrts%?\\t%0, %1"
686   [(set_attr "predicable" "yes")
687    (set_attr "type" "fdivs")]
688 )
689
690 (define_insn "*sqrtdf2_vfp"
691   [(set (match_operand:DF          0 "s_register_operand" "=w")
692         (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
693   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
694   "fsqrtd%?\\t%P0, %P1"
695   [(set_attr "predicable" "yes")
696    (set_attr "type" "fdivd")]
697 )
698
699
700 ;; Patterns to split/copy vfp condition flags.
701
702 (define_insn "*movcc_vfp"
703   [(set (reg CC_REGNUM)
704         (reg VFPCC_REGNUM))]
705   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
706   "fmstat%?"
707   [(set_attr "conds" "set")
708    (set_attr "type" "f_flag")]
709 )
710
711 (define_insn_and_split "*cmpsf_split_vfp"
712   [(set (reg:CCFP CC_REGNUM)
713         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w")
714                       (match_operand:SF 1 "vfp_compare_operand" "wG")))]
715   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
716   "#"
717   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
718   [(set (reg:CCFP VFPCC_REGNUM)
719         (compare:CCFP (match_dup 0)
720                       (match_dup 1)))
721    (set (reg:CCFP CC_REGNUM)
722         (reg:CCFP VFPCC_REGNUM))]
723   ""
724 )
725
726 (define_insn_and_split "*cmpsf_trap_split_vfp"
727   [(set (reg:CCFPE CC_REGNUM)
728         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w")
729                        (match_operand:SF 1 "vfp_compare_operand" "wG")))]
730   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
731   "#"
732   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
733   [(set (reg:CCFPE VFPCC_REGNUM)
734         (compare:CCFPE (match_dup 0)
735                        (match_dup 1)))
736    (set (reg:CCFPE CC_REGNUM)
737         (reg:CCFPE VFPCC_REGNUM))]
738   ""
739 )
740
741 (define_insn_and_split "*cmpdf_split_vfp"
742   [(set (reg:CCFP CC_REGNUM)
743         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w")
744                       (match_operand:DF 1 "vfp_compare_operand" "wG")))]
745   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
746   "#"
747   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
748   [(set (reg:CCFP VFPCC_REGNUM)
749         (compare:CCFP (match_dup 0)
750                        (match_dup 1)))
751    (set (reg:CCFP CC_REGNUM)
752         (reg:CCFPE VFPCC_REGNUM))]
753   ""
754 )
755
756 (define_insn_and_split "*cmpdf_trap_split_vfp"
757   [(set (reg:CCFPE CC_REGNUM)
758         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w")
759                        (match_operand:DF 1 "vfp_compare_operand" "wG")))]
760   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
761   "#"
762   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
763   [(set (reg:CCFPE VFPCC_REGNUM)
764         (compare:CCFPE (match_dup 0)
765                        (match_dup 1)))
766    (set (reg:CCFPE CC_REGNUM)
767         (reg:CCFPE VFPCC_REGNUM))]
768   ""
769 )
770
771
772 ;; Comparison patterns
773
774 (define_insn "*cmpsf_vfp"
775   [(set (reg:CCFP VFPCC_REGNUM)
776         (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w,w")
777                       (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
778   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
779   "@
780    fcmps%?\\t%0, %1
781    fcmpzs%?\\t%0"
782   [(set_attr "predicable" "yes")
783    (set_attr "type" "ffarith")]
784 )
785
786 (define_insn "*cmpsf_trap_vfp"
787   [(set (reg:CCFPE VFPCC_REGNUM)
788         (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w,w")
789                        (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
790   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
791   "@
792    fcmpes%?\\t%0, %1
793    fcmpezs%?\\t%0"
794   [(set_attr "predicable" "yes")
795    (set_attr "type" "ffarith")]
796 )
797
798 (define_insn "*cmpdf_vfp"
799   [(set (reg:CCFP VFPCC_REGNUM)
800         (compare:CCFP (match_operand:DF 0 "s_register_operand"  "w,w")
801                       (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
802   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
803   "@
804    fcmpd%?\\t%P0, %P1
805    fcmpzd%?\\t%P0"
806   [(set_attr "predicable" "yes")
807    (set_attr "type" "ffarith")]
808 )
809
810 (define_insn "*cmpdf_trap_vfp"
811   [(set (reg:CCFPE VFPCC_REGNUM)
812         (compare:CCFPE (match_operand:DF 0 "s_register_operand"  "w,w")
813                        (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
814   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
815   "@
816    fcmped%?\\t%P0, %P1
817    fcmpezd%?\\t%P0"
818   [(set_attr "predicable" "yes")
819    (set_attr "type" "ffarith")]
820 )
821
822
823 ;; Store multiple insn used in function prologue.
824
825 (define_insn "*push_multi_vfp"
826   [(match_parallel 2 "multi_register_push"
827     [(set (match_operand:BLK 0 "memory_operand" "=m")
828           (unspec:BLK [(match_operand:DF 1 "s_register_operand" "w")]
829                       UNSPEC_PUSH_MULT))])]
830   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
831   "* return vfp_output_fstmx (operands);"
832   [(set_attr "type" "f_stored")]
833 )
834
835
836 ;; Unimplemented insns:
837 ;; fldm*
838 ;; fstm*
839 ;; fmdhr et al (VFPv1)
840 ;; Support for xD (single precision only) variants.
841 ;; fmrrs, fmsrr