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