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