* arm.md (bunordered, bordered, bungt, bunlt, bunge, bunle, buneq)
[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, 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 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 "*
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,*")]
178 )
179
180
181 ;; SFmode moves
182
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,*,*,*")]
202 )
203
204
205 ;; DFmode moves
206
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,*,*,*")]
238 )
239
240
241 ;; Conditional move patterns
242
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")]
264 )
265
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")]
287 )
288
289
290 ;; Sign manipulation functions
291
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")]
299 )
300
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")]
308 )
309
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")]
319 )
320
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;
341
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]);
347
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")]
365 )
366
367
368 ;; Arithmetic insns
369
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")]
378 )
379
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")]
388 )
389
390
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")]
399 )
400
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")]
409 )
410
411
412 ;; Division insns
413
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")]
422 )
423
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")]
432 )
433
434
435 ;; Multiplication insns
436
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")]
445 )
446
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")]
455 )
456
457
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")]
466 )
467
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")]
476 )
477
478
479 ;; Multiply-accumulate insns
480
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")]
491 )
492
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")]
502 )
503
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")]
514 )
515
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")]
525 )
526
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")]
537 )
538
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")]
548 )
549
550
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")]
562 )
563
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")]
574 )
575
576
577 ;; Conversion routines
578
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")]
586 )
587
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")]
595 )
596
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")]
604 )
605
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")]
613 )
614
615
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")]
623 )
624
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")]
632 )
633
634
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")]
642 )
643
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")]
651 )
652
653
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")]
661 )
662
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")]
670 )
671
672
673 ;; Sqrt insns.
674
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")]
682 )
683
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")]
691 )
692
693
694 ;; Patterns to split/copy vfp condition flags.
695
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")]
703 )
704
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 ""
718 )
719
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 ""
733 )
734
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 ""
748 )
749
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 ""
763 )
764
765
766 ;; Comparison patterns
767
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")]
778 )
779
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")]
790 )
791
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")]
802 )
803
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")]
814 )
815
816
817 ;; Store multiple insn used in function prologue.
818
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")]
827 )
828
829
830 ;; Unimplemented insns:
831 ;; fldm*
832 ;; fstm*
833 ;; fmdhr et al (VFPv1)
834 ;; Support for xD (single precision only) variants.
835 ;; fmrrs, fmsrr