1 ;; ARM VFP instruction patterns
2 ;; Copyright (C) 2003-2017 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery.
5 ;; This file is part of GCC.
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 3, or (at your option)
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.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>. */
21 ;; Patterns for HI moves which provide more data transfer instructions when VFP
22 ;; support is enabled.
23 (define_insn "*arm_movhi_vfp"
25 (match_operand:HI 0 "nonimmediate_operand"
26 "=rk, r, r, m, r, *t, r, *t")
27 (match_operand:HI 1 "general_operand"
28 "rIk, K, n, r, mi, r, *t, *t"))]
29 "TARGET_ARM && TARGET_HARD_FLOAT
30 && !TARGET_VFP_FP16INST
31 && (register_operand (operands[0], HImode)
32 || register_operand (operands[1], HImode))"
34 switch (which_alternative)
37 return "mov%?\t%0, %1\t%@ movhi";
39 return "mvn%?\t%0, #%B1\t%@ movhi";
41 return "movw%?\t%0, %L1\t%@ movhi";
43 return "strh%?\t%1, %0\t%@ movhi";
45 return "ldrh%?\t%0, %1\t%@ movhi";
48 return "vmov%?\t%0, %1\t%@ int";
50 return "vmov%?.f32\t%0, %1\t%@ int";
55 [(set_attr "predicable" "yes")
56 (set_attr_alternative "type"
58 (match_operand 1 "const_int_operand" "")
59 (const_string "mov_imm")
60 (const_string "mov_reg"))
61 (const_string "mvn_imm")
62 (const_string "mov_imm")
63 (const_string "store_4")
64 (const_string "load_4")
65 (const_string "f_mcr")
66 (const_string "f_mrc")
67 (const_string "fmov")])
68 (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
69 (set_attr "pool_range" "*, *, *, *, 256, *, *, *")
70 (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *")
71 (set_attr "length" "4")]
74 (define_insn "*thumb2_movhi_vfp"
76 (match_operand:HI 0 "nonimmediate_operand"
77 "=rk, r, l, r, m, r, *t, r, *t")
78 (match_operand:HI 1 "general_operand"
79 "rk, I, Py, n, r, m, r, *t, *t"))]
80 "TARGET_THUMB2 && TARGET_HARD_FLOAT
81 && !TARGET_VFP_FP16INST
82 && (register_operand (operands[0], HImode)
83 || register_operand (operands[1], HImode))"
85 switch (which_alternative)
90 return "mov%?\t%0, %1\t%@ movhi";
92 return "movw%?\t%0, %L1\t%@ movhi";
94 return "strh%?\t%1, %0\t%@ movhi";
96 return "ldrh%?\t%0, %1\t%@ movhi";
99 return "vmov%?\t%0, %1\t%@ int";
101 return "vmov%?.f32\t%0, %1\t%@ int";
106 [(set_attr "predicable" "yes")
107 (set_attr "predicable_short_it"
108 "yes, no, yes, no, no, no, no, no, no")
110 "mov_reg, mov_imm, mov_imm, mov_imm, store_4, load_4,\
112 (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *")
113 (set_attr "pool_range" "*, *, *, *, *, 4094, *, *, *")
114 (set_attr "neg_pool_range" "*, *, *, *, *, 250, *, *, *")
115 (set_attr "length" "2, 4, 2, 4, 4, 4, 4, 4, 4")]
118 ;; Patterns for HI moves which provide more data transfer instructions when FP16
119 ;; instructions are available.
120 (define_insn "*arm_movhi_fp16"
122 (match_operand:HI 0 "nonimmediate_operand"
123 "=r, r, r, m, r, *t, r, *t")
124 (match_operand:HI 1 "general_operand"
125 "rIk, K, n, r, mi, r, *t, *t"))]
126 "TARGET_ARM && TARGET_VFP_FP16INST
127 && (register_operand (operands[0], HImode)
128 || register_operand (operands[1], HImode))"
130 switch (which_alternative)
133 return "mov%?\t%0, %1\t%@ movhi";
135 return "mvn%?\t%0, #%B1\t%@ movhi";
137 return "movw%?\t%0, %L1\t%@ movhi";
139 return "strh%?\t%1, %0\t%@ movhi";
141 return "ldrh%?\t%0, %1\t%@ movhi";
144 return "vmov.f16\t%0, %1\t%@ int";
146 return "vmov%?.f32\t%0, %1\t%@ int";
151 [(set_attr "predicable" "yes, yes, yes, yes, yes, no, no, yes")
152 (set_attr_alternative "type"
154 (match_operand 1 "const_int_operand" "")
155 (const_string "mov_imm")
156 (const_string "mov_reg"))
157 (const_string "mvn_imm")
158 (const_string "mov_imm")
159 (const_string "store_4")
160 (const_string "load_4")
161 (const_string "f_mcr")
162 (const_string "f_mrc")
163 (const_string "fmov")])
164 (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
165 (set_attr "pool_range" "*, *, *, *, 256, *, *, *")
166 (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *")
167 (set_attr "length" "4")]
170 (define_insn "*thumb2_movhi_fp16"
172 (match_operand:HI 0 "nonimmediate_operand"
173 "=rk, r, l, r, m, r, *t, r, *t")
174 (match_operand:HI 1 "general_operand"
175 "rk, I, Py, n, r, m, r, *t, *t"))]
176 "TARGET_THUMB2 && TARGET_VFP_FP16INST
177 && (register_operand (operands[0], HImode)
178 || register_operand (operands[1], HImode))"
180 switch (which_alternative)
185 return "mov%?\t%0, %1\t%@ movhi";
187 return "movw%?\t%0, %L1\t%@ movhi";
189 return "strh%?\t%1, %0\t%@ movhi";
191 return "ldrh%?\t%0, %1\t%@ movhi";
194 return "vmov.f16\t%0, %1\t%@ int";
196 return "vmov%?.f32\t%0, %1\t%@ int";
201 [(set_attr "predicable"
202 "yes, yes, yes, yes, yes, yes, no, no, yes")
203 (set_attr "predicable_short_it"
204 "yes, no, yes, no, no, no, no, no, no")
206 "mov_reg, mov_imm, mov_imm, mov_imm, store_4, load_4,\
208 (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *")
209 (set_attr "pool_range" "*, *, *, *, *, 4094, *, *, *")
210 (set_attr "neg_pool_range" "*, *, *, *, *, 250, *, *, *")
211 (set_attr "length" "2, 4, 2, 4, 4, 4, 4, 4, 4")]
215 ;; ??? For now do not allow loading constants into vfp regs. This causes
216 ;; problems because small constants get converted into adds.
217 (define_insn "*arm_movsi_vfp"
218 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv")
219 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk,r,*t,*t,*Uvi,*t"))]
220 "TARGET_ARM && TARGET_HARD_FLOAT
221 && ( s_register_operand (operands[0], SImode)
222 || s_register_operand (operands[1], SImode))"
224 switch (which_alternative)
227 return \"mov%?\\t%0, %1\";
229 return \"mvn%?\\t%0, #%B1\";
231 return \"movw%?\\t%0, %1\";
233 return \"ldr%?\\t%0, %1\";
235 return \"str%?\\t%1, %0\";
237 return \"vmov%?\\t%0, %1\\t%@ int\";
239 return \"vmov%?\\t%0, %1\\t%@ int\";
241 return \"vmov%?.f32\\t%0, %1\\t%@ int\";
243 return output_move_vfp (operands);
248 [(set_attr "predicable" "yes")
249 (set_attr "type" "mov_reg,mov_reg,mvn_imm,mov_imm,load_4,store_4,
250 f_mcr,f_mrc,fmov,f_loads,f_stores")
251 (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*")
252 (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")]
255 ;; See thumb2.md:thumb2_movsi_insn for an explanation of the split
256 ;; high/low register alternatives for loads and stores here.
257 ;; The l/Py alternative should come after r/I to ensure that the short variant
258 ;; is chosen with length 2 when the instruction is predicated for
260 (define_insn "*thumb2_movsi_vfp"
261 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r, l,*hk,m, *m,*t, r,*t,*t, *Uv")
262 (match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,*mi,l,*hk, r,*t,*t,*Uvi,*t"))]
263 "TARGET_THUMB2 && TARGET_HARD_FLOAT
264 && ( s_register_operand (operands[0], SImode)
265 || s_register_operand (operands[1], SImode))"
267 switch (which_alternative)
272 return \"mov%?\\t%0, %1\";
274 return \"mvn%?\\t%0, #%B1\";
276 return \"movw%?\\t%0, %1\";
279 return \"ldr%?\\t%0, %1\";
282 return \"str%?\\t%1, %0\";
284 return \"vmov%?\\t%0, %1\\t%@ int\";
286 return \"vmov%?\\t%0, %1\\t%@ int\";
288 return \"vmov%?.f32\\t%0, %1\\t%@ int\";
290 return output_move_vfp (operands);
295 [(set_attr "predicable" "yes")
296 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no")
297 (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_imm,load_4,load_4,store_4,store_4,f_mcr,f_mrc,fmov,f_loads,f_stores")
298 (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4")
299 (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*")
300 (set_attr "neg_pool_range" "*,*,*,*,*, 0, 0,*,*,*,*,*,1008,*")]
306 (define_insn "*movdi_vfp"
307 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,q,q,m,w,!r,w,w, Uv")
308 (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,q,r,w,w,Uvi,w"))]
309 "TARGET_32BIT && TARGET_HARD_FLOAT
310 && ( register_operand (operands[0], DImode)
311 || register_operand (operands[1], DImode))
312 && !(TARGET_NEON && CONST_INT_P (operands[1])
313 && neon_immediate_valid_for_move (operands[1], DImode, NULL, NULL))"
315 switch (which_alternative)
325 return output_move_double (operands, true, NULL);
327 return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\";
329 return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\";
331 if (TARGET_VFP_SINGLE)
332 return \"vmov%?.f32\\t%0, %1\\t%@ int\;vmov%?.f32\\t%p0, %p1\\t%@ int\";
334 return \"vmov%?.f64\\t%P0, %P1\\t%@ int\";
336 return output_move_vfp (operands);
341 [(set_attr "type" "multiple,multiple,multiple,multiple,load_8,load_8,store_8,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored")
342 (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8)
343 (eq_attr "alternative" "2") (const_int 12)
344 (eq_attr "alternative" "3") (const_int 16)
345 (eq_attr "alternative" "4,5,6")
346 (symbol_ref "arm_count_output_move_double_insns (operands) * 4")
347 (eq_attr "alternative" "9")
349 (match_test "TARGET_VFP_SINGLE")
353 (set_attr "predicable" "yes")
354 (set_attr "arm_pool_range" "*,*,*,*,1020,4096,*,*,*,*,1020,*")
355 (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
356 (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
357 (set (attr "ce_count") (symbol_ref "get_attr_length (insn) / 4"))
358 (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
363 (define_insn "*movhf_vfp_fp16"
364 [(set (match_operand:HF 0 "nonimmediate_operand"
365 "= r,m,t,r,t,r,t,t,Um,r")
366 (match_operand:HF 1 "general_operand"
367 " m,r,t,r,r,t,Dv,Um,t,F"))]
369 && TARGET_VFP_FP16INST
370 && (s_register_operand (operands[0], HFmode)
371 || s_register_operand (operands[1], HFmode))"
373 switch (which_alternative)
375 case 0: /* ARM register from memory. */
376 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
377 case 1: /* Memory from ARM register. */
378 return \"strh%?\\t%1, %0\\t%@ __fp16\";
379 case 2: /* S register from S register. */
380 return \"vmov\\t%0, %1\t%@ __fp16\";
381 case 3: /* ARM register from ARM register. */
382 return \"mov%?\\t%0, %1\\t%@ __fp16\";
383 case 4: /* S register from ARM register. */
384 case 5: /* ARM register from S register. */
385 case 6: /* S register from immediate. */
386 return \"vmov.f16\\t%0, %1\t%@ __fp16\";
387 case 7: /* S register from memory. */
388 return \"vld1.16\\t{%z0}, %A1\";
389 case 8: /* Memory from S register. */
390 return \"vst1.16\\t{%z1}, %A0\";
391 case 9: /* ARM register from constant. */
396 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
398 ops[0] = operands[0];
399 ops[1] = GEN_INT (bits);
400 ops[2] = GEN_INT (bits & 0xff00);
401 ops[3] = GEN_INT (bits & 0x00ff);
404 output_asm_insn (\"movw\\t%0, %1\", ops);
406 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
413 [(set_attr "predicable" "yes, yes, no, yes, no, no, no, no, no, no")
414 (set_attr "predicable_short_it" "no, no, no, yes,\
417 (set_attr_alternative "type"
418 [(const_string "load_4") (const_string "store_4")
419 (const_string "fmov") (const_string "mov_reg")
420 (const_string "f_mcr") (const_string "f_mrc")
421 (const_string "fconsts") (const_string "neon_load1_1reg")
422 (const_string "neon_store1_1reg")
423 (if_then_else (match_test "arm_arch_thumb2")
424 (const_string "mov_imm")
425 (const_string "multiple"))])
426 (set_attr_alternative "length"
427 [(const_int 4) (const_int 4)
428 (const_int 4) (const_int 4)
429 (const_int 4) (const_int 4)
430 (const_int 4) (const_int 4)
432 (if_then_else (match_test "arm_arch_thumb2")
437 (define_insn "*movhf_vfp_neon"
438 [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r")
439 (match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))]
441 && TARGET_HARD_FLOAT && TARGET_NEON_FP16
442 && !TARGET_VFP_FP16INST
443 && ( s_register_operand (operands[0], HFmode)
444 || s_register_operand (operands[1], HFmode))"
446 switch (which_alternative)
448 case 0: /* S register from memory */
449 return \"vld1.16\\t{%z0}, %A1\";
450 case 1: /* memory from S register */
451 return \"vst1.16\\t{%z1}, %A0\";
452 case 2: /* ARM register from memory */
453 return \"ldrh\\t%0, %1\\t%@ __fp16\";
454 case 3: /* memory from ARM register */
455 return \"strh\\t%1, %0\\t%@ __fp16\";
456 case 4: /* S register from S register */
457 return \"vmov.f32\\t%0, %1\";
458 case 5: /* ARM register from ARM register */
459 return \"mov\\t%0, %1\\t%@ __fp16\";
460 case 6: /* S register from ARM register */
461 return \"vmov\\t%0, %1\";
462 case 7: /* ARM register from S register */
463 return \"vmov\\t%0, %1\";
464 case 8: /* ARM register from constant */
469 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
471 ops[0] = operands[0];
472 ops[1] = GEN_INT (bits);
473 ops[2] = GEN_INT (bits & 0xff00);
474 ops[3] = GEN_INT (bits & 0x00ff);
477 output_asm_insn (\"movw\\t%0, %1\", ops);
479 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
486 [(set_attr "conds" "unconditional")
487 (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\
488 load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
489 (set_attr "length" "4,4,4,4,4,4,4,4,8")]
492 ;; FP16 without element load/store instructions.
493 (define_insn "*movhf_vfp"
494 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
495 (match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))]
499 && !TARGET_VFP_FP16INST
500 && ( s_register_operand (operands[0], HFmode)
501 || s_register_operand (operands[1], HFmode))"
503 switch (which_alternative)
505 case 0: /* ARM register from memory */
506 return \"ldrh\\t%0, %1\\t%@ __fp16\";
507 case 1: /* memory from ARM register */
508 return \"strh\\t%1, %0\\t%@ __fp16\";
509 case 2: /* S register from S register */
510 return \"vmov.f32\\t%0, %1\";
511 case 3: /* ARM register from ARM register */
512 return \"mov\\t%0, %1\\t%@ __fp16\";
513 case 4: /* S register from ARM register */
514 return \"vmov\\t%0, %1\";
515 case 5: /* ARM register from S register */
516 return \"vmov\\t%0, %1\";
517 case 6: /* ARM register from constant */
522 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
524 ops[0] = operands[0];
525 ops[1] = GEN_INT (bits);
526 ops[2] = GEN_INT (bits & 0xff00);
527 ops[3] = GEN_INT (bits & 0x00ff);
530 output_asm_insn (\"movw\\t%0, %1\", ops);
532 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
539 [(set_attr "conds" "unconditional")
540 (set_attr "type" "load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
541 (set_attr "length" "4,4,4,4,4,4,8")]
546 ;; Disparage the w<->r cases because reloading an invalid address is
547 ;; preferable to loading the value via integer registers.
549 (define_insn "*movsf_vfp"
550 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t ,Uv,r ,m,t,r")
551 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
552 "TARGET_ARM && TARGET_HARD_FLOAT
553 && ( s_register_operand (operands[0], SFmode)
554 || s_register_operand (operands[1], SFmode))"
556 switch (which_alternative)
559 return \"vmov%?\\t%0, %1\";
561 return \"vmov%?\\t%0, %1\";
563 return \"vmov%?.f32\\t%0, %1\";
565 return output_move_vfp (operands);
567 return \"ldr%?\\t%0, %1\\t%@ float\";
569 return \"str%?\\t%1, %0\\t%@ float\";
571 return \"vmov%?.f32\\t%0, %1\";
573 return \"mov%?\\t%0, %1\\t%@ float\";
578 [(set_attr "predicable" "yes")
580 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
581 (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
582 (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
585 (define_insn "*thumb2_movsf_vfp"
586 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t ,Uv,r ,m,t,r")
587 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
588 "TARGET_THUMB2 && TARGET_HARD_FLOAT
589 && ( s_register_operand (operands[0], SFmode)
590 || s_register_operand (operands[1], SFmode))"
592 switch (which_alternative)
595 return \"vmov%?\\t%0, %1\";
597 return \"vmov%?\\t%0, %1\";
599 return \"vmov%?.f32\\t%0, %1\";
601 return output_move_vfp (operands);
603 return \"ldr%?\\t%0, %1\\t%@ float\";
605 return \"str%?\\t%1, %0\\t%@ float\";
607 return \"vmov%?.f32\\t%0, %1\";
609 return \"mov%?\\t%0, %1\\t%@ float\";
614 [(set_attr "predicable" "yes")
615 (set_attr "predicable_short_it" "no")
617 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
618 (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*")
619 (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
624 (define_insn "*movdf_vfp"
625 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r, m,w,r")
626 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,G,UvF,w ,mF,r,w,r"))]
627 "TARGET_ARM && TARGET_HARD_FLOAT
628 && ( register_operand (operands[0], DFmode)
629 || register_operand (operands[1], DFmode))"
632 switch (which_alternative)
635 return \"vmov%?\\t%P0, %Q1, %R1\";
637 return \"vmov%?\\t%Q0, %R0, %P1\";
639 gcc_assert (TARGET_VFP_DOUBLE);
640 return \"vmov%?.f64\\t%P0, %1\";
642 gcc_assert (TARGET_VFP_DOUBLE);
643 return \"vmov.i64\\t%P0, #0\\t%@ float\";
645 return output_move_vfp (operands);
647 return output_move_double (operands, true, NULL);
649 if (TARGET_VFP_SINGLE)
650 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
652 return \"vmov%?.f64\\t%P0, %P1\";
660 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,f_stored,\
661 load_8,store_8,ffarithd,multiple")
662 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
663 (eq_attr "alternative" "8")
665 (match_test "TARGET_VFP_SINGLE")
669 (set_attr "predicable" "yes,yes,yes,no,yes,yes,yes,yes,yes,yes")
670 (set_attr "pool_range" "*,*,*,*,1020,*,1020,*,*,*")
671 (set_attr "neg_pool_range" "*,*,*,*,1004,*,1004,*,*,*")
672 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
675 (define_insn "*thumb2_movdf_vfp"
676 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r ,m,w,r")
677 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,G,UvF,w, mF,r, w,r"))]
678 "TARGET_THUMB2 && TARGET_HARD_FLOAT
679 && ( register_operand (operands[0], DFmode)
680 || register_operand (operands[1], DFmode))"
683 switch (which_alternative)
686 return \"vmov%?\\t%P0, %Q1, %R1\";
688 return \"vmov%?\\t%Q0, %R0, %P1\";
690 gcc_assert (TARGET_VFP_DOUBLE);
691 return \"vmov%?.f64\\t%P0, %1\";
693 gcc_assert (TARGET_VFP_DOUBLE);
694 return \"vmov.i64\\t%P0, #0\\t%@ float\";
696 return output_move_vfp (operands);
697 case 6: case 7: case 9:
698 return output_move_double (operands, true, NULL);
700 if (TARGET_VFP_SINGLE)
701 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
703 return \"vmov%?.f64\\t%P0, %P1\";
709 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,\
710 f_stored,load_8,store_8,ffarithd,multiple")
711 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
712 (eq_attr "alternative" "8")
714 (match_test "TARGET_VFP_SINGLE")
718 (set_attr "pool_range" "*,*,*,*,1018,*,4094,*,*,*")
719 (set_attr "neg_pool_range" "*,*,*,*,1008,*,0,*,*,*")
720 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
724 ;; Conditional move patterns
726 (define_insn "*movsfcc_vfp"
727 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
729 (match_operator 3 "arm_comparison_operator"
730 [(match_operand 4 "cc_register" "") (const_int 0)])
731 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
732 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
733 "TARGET_ARM && TARGET_HARD_FLOAT"
737 vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
740 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
743 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
744 [(set_attr "conds" "use")
745 (set_attr "length" "4,4,8,4,4,8,4,4,8")
746 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
749 (define_insn "*thumb2_movsfcc_vfp"
750 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
752 (match_operator 3 "arm_comparison_operator"
753 [(match_operand 4 "cc_register" "") (const_int 0)])
754 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
755 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
756 "TARGET_THUMB2 && TARGET_HARD_FLOAT && !arm_restrict_it"
758 it\\t%D3\;vmov%D3.f32\\t%0, %2
759 it\\t%d3\;vmov%d3.f32\\t%0, %1
760 ite\\t%D3\;vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
761 it\\t%D3\;vmov%D3\\t%0, %2
762 it\\t%d3\;vmov%d3\\t%0, %1
763 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
764 it\\t%D3\;vmov%D3\\t%0, %2
765 it\\t%d3\;vmov%d3\\t%0, %1
766 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
767 [(set_attr "conds" "use")
768 (set_attr "length" "6,6,10,6,6,10,6,6,10")
769 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
772 (define_insn "*movdfcc_vfp"
773 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
775 (match_operator 3 "arm_comparison_operator"
776 [(match_operand 4 "cc_register" "") (const_int 0)])
777 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
778 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
779 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
781 vmov%D3.f64\\t%P0, %P2
782 vmov%d3.f64\\t%P0, %P1
783 vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
784 vmov%D3\\t%P0, %Q2, %R2
785 vmov%d3\\t%P0, %Q1, %R1
786 vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
787 vmov%D3\\t%Q0, %R0, %P2
788 vmov%d3\\t%Q0, %R0, %P1
789 vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
790 [(set_attr "conds" "use")
791 (set_attr "length" "4,4,8,4,4,8,4,4,8")
792 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcr,f_mrrc,f_mrrc,f_mrrc")]
795 (define_insn "*thumb2_movdfcc_vfp"
796 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
798 (match_operator 3 "arm_comparison_operator"
799 [(match_operand 4 "cc_register" "") (const_int 0)])
800 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
801 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
802 "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && !arm_restrict_it"
804 it\\t%D3\;vmov%D3.f64\\t%P0, %P2
805 it\\t%d3\;vmov%d3.f64\\t%P0, %P1
806 ite\\t%D3\;vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
807 it\t%D3\;vmov%D3\\t%P0, %Q2, %R2
808 it\t%d3\;vmov%d3\\t%P0, %Q1, %R1
809 ite\\t%D3\;vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
810 it\t%D3\;vmov%D3\\t%Q0, %R0, %P2
811 it\t%d3\;vmov%d3\\t%Q0, %R0, %P1
812 ite\\t%D3\;vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
813 [(set_attr "conds" "use")
814 (set_attr "length" "6,6,10,6,6,10,6,6,10")
815 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcrr,f_mrrc,f_mrrc,f_mrrc")]
819 ;; Sign manipulation functions
821 (define_insn "*abssf2_vfp"
822 [(set (match_operand:SF 0 "s_register_operand" "=t")
823 (abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
824 "TARGET_32BIT && TARGET_HARD_FLOAT"
825 "vabs%?.f32\\t%0, %1"
826 [(set_attr "predicable" "yes")
827 (set_attr "predicable_short_it" "no")
828 (set_attr "type" "ffariths")]
831 (define_insn "*absdf2_vfp"
832 [(set (match_operand:DF 0 "s_register_operand" "=w")
833 (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
834 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
835 "vabs%?.f64\\t%P0, %P1"
836 [(set_attr "predicable" "yes")
837 (set_attr "predicable_short_it" "no")
838 (set_attr "type" "ffarithd")]
841 (define_insn "*negsf2_vfp"
842 [(set (match_operand:SF 0 "s_register_operand" "=t,?r")
843 (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))]
844 "TARGET_32BIT && TARGET_HARD_FLOAT"
847 eor%?\\t%0, %1, #-2147483648"
848 [(set_attr "predicable" "yes")
849 (set_attr "predicable_short_it" "no")
850 (set_attr "type" "ffariths")]
853 (define_insn_and_split "*negdf2_vfp"
854 [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r")
855 (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
856 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
858 vneg%?.f64\\t%P0, %P1
861 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
862 && arm_general_register_operand (operands[0], DFmode)"
863 [(set (match_dup 0) (match_dup 1))]
865 if (REGNO (operands[0]) == REGNO (operands[1]))
867 operands[0] = gen_highpart (SImode, operands[0]);
868 operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
872 rtx in_hi, in_lo, out_hi, out_lo;
874 in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
875 GEN_INT (0x80000000));
876 in_lo = gen_lowpart (SImode, operands[1]);
877 out_hi = gen_highpart (SImode, operands[0]);
878 out_lo = gen_lowpart (SImode, operands[0]);
880 if (REGNO (in_lo) == REGNO (out_hi))
882 emit_insn (gen_rtx_SET (out_lo, in_lo));
883 operands[0] = out_hi;
888 emit_insn (gen_rtx_SET (out_hi, in_hi));
889 operands[0] = out_lo;
894 [(set_attr "predicable" "yes")
895 (set_attr "predicable_short_it" "no")
896 (set_attr "length" "4,4,8")
897 (set_attr "type" "ffarithd")]
900 ;; ABS and NEG for FP16.
901 (define_insn "<absneg_str>hf2"
902 [(set (match_operand:HF 0 "s_register_operand" "=w")
903 (ABSNEG:HF (match_operand:HF 1 "s_register_operand" "w")))]
904 "TARGET_VFP_FP16INST"
905 "v<absneg_str>.f16\t%0, %1"
906 [(set_attr "conds" "unconditional")
907 (set_attr "type" "ffariths")]
910 (define_expand "neon_vabshf"
912 (match_operand:HF 0 "s_register_operand")
913 (abs:HF (match_operand:HF 1 "s_register_operand")))]
914 "TARGET_VFP_FP16INST"
916 emit_insn (gen_abshf2 (operands[0], operands[1]));
921 (define_insn "neon_v<fp16_rnd_str>hf"
922 [(set (match_operand:HF 0 "s_register_operand" "=w")
924 [(match_operand:HF 1 "s_register_operand" "w")]
926 "TARGET_VFP_FP16INST"
927 "<fp16_rnd_insn>.f16\t%0, %1"
928 [(set_attr "conds" "unconditional")
929 (set_attr "type" "neon_fp_round_s")]
932 (define_insn "neon_vrndihf"
933 [(set (match_operand:HF 0 "s_register_operand" "=w")
935 [(match_operand:HF 1 "s_register_operand" "w")]
937 "TARGET_VFP_FP16INST"
939 [(set_attr "conds" "unconditional")
940 (set_attr "type" "neon_fp_round_s")]
945 (define_insn "addhf3"
947 (match_operand:HF 0 "s_register_operand" "=w")
949 (match_operand:HF 1 "s_register_operand" "w")
950 (match_operand:HF 2 "s_register_operand" "w")))]
951 "TARGET_VFP_FP16INST"
952 "vadd.f16\t%0, %1, %2"
953 [(set_attr "conds" "unconditional")
954 (set_attr "type" "fadds")]
957 (define_insn "*addsf3_vfp"
958 [(set (match_operand:SF 0 "s_register_operand" "=t")
959 (plus:SF (match_operand:SF 1 "s_register_operand" "t")
960 (match_operand:SF 2 "s_register_operand" "t")))]
961 "TARGET_32BIT && TARGET_HARD_FLOAT"
962 "vadd%?.f32\\t%0, %1, %2"
963 [(set_attr "predicable" "yes")
964 (set_attr "predicable_short_it" "no")
965 (set_attr "type" "fadds")]
968 (define_insn "*adddf3_vfp"
969 [(set (match_operand:DF 0 "s_register_operand" "=w")
970 (plus:DF (match_operand:DF 1 "s_register_operand" "w")
971 (match_operand:DF 2 "s_register_operand" "w")))]
972 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
973 "vadd%?.f64\\t%P0, %P1, %P2"
974 [(set_attr "predicable" "yes")
975 (set_attr "predicable_short_it" "no")
976 (set_attr "type" "faddd")]
979 (define_insn "subhf3"
981 (match_operand:HF 0 "s_register_operand" "=w")
983 (match_operand:HF 1 "s_register_operand" "w")
984 (match_operand:HF 2 "s_register_operand" "w")))]
985 "TARGET_VFP_FP16INST"
986 "vsub.f16\t%0, %1, %2"
987 [(set_attr "conds" "unconditional")
988 (set_attr "type" "fadds")]
991 (define_insn "*subsf3_vfp"
992 [(set (match_operand:SF 0 "s_register_operand" "=t")
993 (minus:SF (match_operand:SF 1 "s_register_operand" "t")
994 (match_operand:SF 2 "s_register_operand" "t")))]
995 "TARGET_32BIT && TARGET_HARD_FLOAT"
996 "vsub%?.f32\\t%0, %1, %2"
997 [(set_attr "predicable" "yes")
998 (set_attr "predicable_short_it" "no")
999 (set_attr "type" "fadds")]
1002 (define_insn "*subdf3_vfp"
1003 [(set (match_operand:DF 0 "s_register_operand" "=w")
1004 (minus:DF (match_operand:DF 1 "s_register_operand" "w")
1005 (match_operand:DF 2 "s_register_operand" "w")))]
1006 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1007 "vsub%?.f64\\t%P0, %P1, %P2"
1008 [(set_attr "predicable" "yes")
1009 (set_attr "predicable_short_it" "no")
1010 (set_attr "type" "faddd")]
1017 (define_insn "divhf3"
1019 (match_operand:HF 0 "s_register_operand" "=w")
1021 (match_operand:HF 1 "s_register_operand" "w")
1022 (match_operand:HF 2 "s_register_operand" "w")))]
1023 "TARGET_VFP_FP16INST"
1024 "vdiv.f16\t%0, %1, %2"
1025 [(set_attr "conds" "unconditional")
1026 (set_attr "type" "fdivs")]
1029 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1030 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1032 (define_insn "*divsf3_vfp"
1033 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1034 (div:SF (match_operand:SF 1 "s_register_operand" "t,t")
1035 (match_operand:SF 2 "s_register_operand" "t,t")))]
1036 "TARGET_32BIT && TARGET_HARD_FLOAT"
1037 "vdiv%?.f32\\t%0, %1, %2"
1038 [(set_attr "predicable" "yes")
1039 (set_attr "predicable_short_it" "no")
1040 (set_attr "arch" "*,armv6_or_vfpv3")
1041 (set_attr "type" "fdivs")]
1044 (define_insn "*divdf3_vfp"
1045 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1046 (div:DF (match_operand:DF 1 "s_register_operand" "w,w")
1047 (match_operand:DF 2 "s_register_operand" "w,w")))]
1048 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1049 "vdiv%?.f64\\t%P0, %P1, %P2"
1050 [(set_attr "predicable" "yes")
1051 (set_attr "predicable_short_it" "no")
1052 (set_attr "arch" "*,armv6_or_vfpv3")
1053 (set_attr "type" "fdivd")]
1057 ;; Multiplication insns
1059 (define_insn "mulhf3"
1061 (match_operand:HF 0 "s_register_operand" "=w")
1062 (mult:HF (match_operand:HF 1 "s_register_operand" "w")
1063 (match_operand:HF 2 "s_register_operand" "w")))]
1064 "TARGET_VFP_FP16INST"
1065 "vmul.f16\t%0, %1, %2"
1066 [(set_attr "conds" "unconditional")
1067 (set_attr "type" "fmuls")]
1070 (define_insn "*mulsf3_vfp"
1071 [(set (match_operand:SF 0 "s_register_operand" "=t")
1072 (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1073 (match_operand:SF 2 "s_register_operand" "t")))]
1074 "TARGET_32BIT && TARGET_HARD_FLOAT"
1075 "vmul%?.f32\\t%0, %1, %2"
1076 [(set_attr "predicable" "yes")
1077 (set_attr "predicable_short_it" "no")
1078 (set_attr "type" "fmuls")]
1081 (define_insn "*muldf3_vfp"
1082 [(set (match_operand:DF 0 "s_register_operand" "=w")
1083 (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1084 (match_operand:DF 2 "s_register_operand" "w")))]
1085 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1086 "vmul%?.f64\\t%P0, %P1, %P2"
1087 [(set_attr "predicable" "yes")
1088 (set_attr "predicable_short_it" "no")
1089 (set_attr "type" "fmuld")]
1092 (define_insn "*mulsf3neghf_vfp"
1093 [(set (match_operand:HF 0 "s_register_operand" "=t")
1094 (mult:HF (neg:HF (match_operand:HF 1 "s_register_operand" "t"))
1095 (match_operand:HF 2 "s_register_operand" "t")))]
1096 "TARGET_VFP_FP16INST && !flag_rounding_math"
1097 "vnmul.f16\\t%0, %1, %2"
1098 [(set_attr "conds" "unconditional")
1099 (set_attr "type" "fmuls")]
1102 (define_insn "*negmulhf3_vfp"
1103 [(set (match_operand:HF 0 "s_register_operand" "=t")
1104 (neg:HF (mult:HF (match_operand:HF 1 "s_register_operand" "t")
1105 (match_operand:HF 2 "s_register_operand" "t"))))]
1106 "TARGET_VFP_FP16INST"
1107 "vnmul.f16\\t%0, %1, %2"
1108 [(set_attr "conds" "unconditional")
1109 (set_attr "type" "fmuls")]
1112 (define_insn "*mulsf3negsf_vfp"
1113 [(set (match_operand:SF 0 "s_register_operand" "=t")
1114 (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
1115 (match_operand:SF 2 "s_register_operand" "t")))]
1116 "TARGET_32BIT && TARGET_HARD_FLOAT && !flag_rounding_math"
1117 "vnmul%?.f32\\t%0, %1, %2"
1118 [(set_attr "predicable" "yes")
1119 (set_attr "predicable_short_it" "no")
1120 (set_attr "type" "fmuls")]
1123 (define_insn "*negmulsf3_vfp"
1124 [(set (match_operand:SF 0 "s_register_operand" "=t")
1125 (neg:SF (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1126 (match_operand:SF 2 "s_register_operand" "t"))))]
1127 "TARGET_32BIT && TARGET_HARD_FLOAT"
1128 "vnmul%?.f32\\t%0, %1, %2"
1129 [(set_attr "predicable" "yes")
1130 (set_attr "predicable_short_it" "no")
1131 (set_attr "type" "fmuls")]
1134 (define_insn "*muldf3negdf_vfp"
1135 [(set (match_operand:DF 0 "s_register_operand" "=w")
1136 (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
1137 (match_operand:DF 2 "s_register_operand" "w")))]
1138 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
1139 && !flag_rounding_math"
1140 "vnmul%?.f64\\t%P0, %P1, %P2"
1141 [(set_attr "predicable" "yes")
1142 (set_attr "predicable_short_it" "no")
1143 (set_attr "type" "fmuld")]
1146 (define_insn "*negmuldf3_vfp"
1147 [(set (match_operand:DF 0 "s_register_operand" "=w")
1148 (neg:DF (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1149 (match_operand:DF 2 "s_register_operand" "w"))))]
1150 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1151 "vnmul%?.f64\\t%P0, %P1, %P2"
1152 [(set_attr "predicable" "yes")
1153 (set_attr "predicable_short_it" "no")
1154 (set_attr "type" "fmuld")]
1158 ;; Multiply-accumulate insns
1161 (define_insn "*mulsf3addhf_vfp"
1162 [(set (match_operand:HF 0 "s_register_operand" "=t")
1164 (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1165 (match_operand:HF 3 "s_register_operand" "t"))
1166 (match_operand:HF 1 "s_register_operand" "0")))]
1167 "TARGET_VFP_FP16INST"
1168 "vmla.f16\\t%0, %2, %3"
1169 [(set_attr "conds" "unconditional")
1170 (set_attr "type" "fmacs")]
1173 (define_insn "*mulsf3addsf_vfp"
1174 [(set (match_operand:SF 0 "s_register_operand" "=t")
1175 (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1176 (match_operand:SF 3 "s_register_operand" "t"))
1177 (match_operand:SF 1 "s_register_operand" "0")))]
1178 "TARGET_32BIT && TARGET_HARD_FLOAT"
1179 "vmla%?.f32\\t%0, %2, %3"
1180 [(set_attr "predicable" "yes")
1181 (set_attr "predicable_short_it" "no")
1182 (set_attr "type" "fmacs")]
1185 (define_insn "*muldf3adddf_vfp"
1186 [(set (match_operand:DF 0 "s_register_operand" "=w")
1187 (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1188 (match_operand:DF 3 "s_register_operand" "w"))
1189 (match_operand:DF 1 "s_register_operand" "0")))]
1190 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1191 "vmla%?.f64\\t%P0, %P2, %P3"
1192 [(set_attr "predicable" "yes")
1193 (set_attr "predicable_short_it" "no")
1194 (set_attr "type" "fmacd")]
1198 (define_insn "*mulhf3subhf_vfp"
1199 [(set (match_operand:HF 0 "s_register_operand" "=t")
1200 (minus:HF (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1201 (match_operand:HF 3 "s_register_operand" "t"))
1202 (match_operand:HF 1 "s_register_operand" "0")))]
1203 "TARGET_VFP_FP16INST"
1204 "vnmls.f16\\t%0, %2, %3"
1205 [(set_attr "conds" "unconditional")
1206 (set_attr "type" "fmacs")]
1209 (define_insn "*mulsf3subsf_vfp"
1210 [(set (match_operand:SF 0 "s_register_operand" "=t")
1211 (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1212 (match_operand:SF 3 "s_register_operand" "t"))
1213 (match_operand:SF 1 "s_register_operand" "0")))]
1214 "TARGET_32BIT && TARGET_HARD_FLOAT"
1215 "vnmls%?.f32\\t%0, %2, %3"
1216 [(set_attr "predicable" "yes")
1217 (set_attr "predicable_short_it" "no")
1218 (set_attr "type" "fmacs")]
1221 (define_insn "*muldf3subdf_vfp"
1222 [(set (match_operand:DF 0 "s_register_operand" "=w")
1223 (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1224 (match_operand:DF 3 "s_register_operand" "w"))
1225 (match_operand:DF 1 "s_register_operand" "0")))]
1226 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1227 "vnmls%?.f64\\t%P0, %P2, %P3"
1228 [(set_attr "predicable" "yes")
1229 (set_attr "predicable_short_it" "no")
1230 (set_attr "type" "fmacd")]
1234 (define_insn "*mulhf3neghfaddhf_vfp"
1235 [(set (match_operand:HF 0 "s_register_operand" "=t")
1236 (minus:HF (match_operand:HF 1 "s_register_operand" "0")
1237 (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1238 (match_operand:HF 3 "s_register_operand" "t"))))]
1239 "TARGET_VFP_FP16INST"
1240 "vmls.f16\\t%0, %2, %3"
1241 [(set_attr "conds" "unconditional")
1242 (set_attr "type" "fmacs")]
1245 (define_insn "*mulsf3negsfaddsf_vfp"
1246 [(set (match_operand:SF 0 "s_register_operand" "=t")
1247 (minus:SF (match_operand:SF 1 "s_register_operand" "0")
1248 (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1249 (match_operand:SF 3 "s_register_operand" "t"))))]
1250 "TARGET_32BIT && TARGET_HARD_FLOAT"
1251 "vmls%?.f32\\t%0, %2, %3"
1252 [(set_attr "predicable" "yes")
1253 (set_attr "predicable_short_it" "no")
1254 (set_attr "type" "fmacs")]
1257 (define_insn "*fmuldf3negdfadddf_vfp"
1258 [(set (match_operand:DF 0 "s_register_operand" "=w")
1259 (minus:DF (match_operand:DF 1 "s_register_operand" "0")
1260 (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1261 (match_operand:DF 3 "s_register_operand" "w"))))]
1262 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1263 "vmls%?.f64\\t%P0, %P2, %P3"
1264 [(set_attr "predicable" "yes")
1265 (set_attr "predicable_short_it" "no")
1266 (set_attr "type" "fmacd")]
1271 (define_insn "*mulhf3neghfsubhf_vfp"
1272 [(set (match_operand:HF 0 "s_register_operand" "=t")
1274 (neg:HF (match_operand:HF 2 "s_register_operand" "t"))
1275 (match_operand:HF 3 "s_register_operand" "t"))
1276 (match_operand:HF 1 "s_register_operand" "0")))]
1277 "TARGET_VFP_FP16INST"
1278 "vnmla.f16\\t%0, %2, %3"
1279 [(set_attr "conds" "unconditional")
1280 (set_attr "type" "fmacs")]
1283 (define_insn "*mulsf3negsfsubsf_vfp"
1284 [(set (match_operand:SF 0 "s_register_operand" "=t")
1286 (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
1287 (match_operand:SF 3 "s_register_operand" "t"))
1288 (match_operand:SF 1 "s_register_operand" "0")))]
1289 "TARGET_32BIT && TARGET_HARD_FLOAT"
1290 "vnmla%?.f32\\t%0, %2, %3"
1291 [(set_attr "predicable" "yes")
1292 (set_attr "predicable_short_it" "no")
1293 (set_attr "type" "fmacs")]
1296 (define_insn "*muldf3negdfsubdf_vfp"
1297 [(set (match_operand:DF 0 "s_register_operand" "=w")
1299 (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
1300 (match_operand:DF 3 "s_register_operand" "w"))
1301 (match_operand:DF 1 "s_register_operand" "0")))]
1302 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1303 "vnmla%?.f64\\t%P0, %P2, %P3"
1304 [(set_attr "predicable" "yes")
1305 (set_attr "predicable_short_it" "no")
1306 (set_attr "type" "fmacd")]
1309 ;; Fused-multiply-accumulate
1311 (define_insn "fmahf4"
1312 [(set (match_operand:HF 0 "register_operand" "=w")
1314 (match_operand:HF 1 "register_operand" "w")
1315 (match_operand:HF 2 "register_operand" "w")
1316 (match_operand:HF 3 "register_operand" "0")))]
1317 "TARGET_VFP_FP16INST"
1318 "vfma.f16\\t%0, %1, %2"
1319 [(set_attr "conds" "unconditional")
1320 (set_attr "type" "ffmas")]
1323 (define_expand "neon_vfmahf"
1324 [(match_operand:HF 0 "s_register_operand")
1325 (match_operand:HF 1 "s_register_operand")
1326 (match_operand:HF 2 "s_register_operand")
1327 (match_operand:HF 3 "s_register_operand")]
1328 "TARGET_VFP_FP16INST"
1330 emit_insn (gen_fmahf4 (operands[0], operands[2], operands[3],
1335 (define_insn "fma<SDF:mode>4"
1336 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1337 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1338 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1339 (match_operand:SDF 3 "register_operand" "0")))]
1340 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1341 "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1342 [(set_attr "predicable" "yes")
1343 (set_attr "predicable_short_it" "no")
1344 (set_attr "type" "ffma<vfp_type>")]
1347 (define_insn "fmsubhf4_fp16"
1348 [(set (match_operand:HF 0 "register_operand" "=w")
1350 (neg:HF (match_operand:HF 1 "register_operand" "w"))
1351 (match_operand:HF 2 "register_operand" "w")
1352 (match_operand:HF 3 "register_operand" "0")))]
1353 "TARGET_VFP_FP16INST"
1354 "vfms.f16\\t%0, %1, %2"
1355 [(set_attr "conds" "unconditional")
1356 (set_attr "type" "ffmas")]
1359 (define_expand "neon_vfmshf"
1360 [(match_operand:HF 0 "s_register_operand")
1361 (match_operand:HF 1 "s_register_operand")
1362 (match_operand:HF 2 "s_register_operand")
1363 (match_operand:HF 3 "s_register_operand")]
1364 "TARGET_VFP_FP16INST"
1366 emit_insn (gen_fmsubhf4_fp16 (operands[0], operands[2], operands[3],
1371 (define_insn "*fmsub<SDF:mode>4"
1372 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1373 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1375 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1376 (match_operand:SDF 3 "register_operand" "0")))]
1377 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1378 "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1379 [(set_attr "predicable" "yes")
1380 (set_attr "predicable_short_it" "no")
1381 (set_attr "type" "ffma<vfp_type>")]
1384 (define_insn "*fnmsubhf4"
1385 [(set (match_operand:HF 0 "register_operand" "=w")
1386 (fma:HF (match_operand:HF 1 "register_operand" "w")
1387 (match_operand:HF 2 "register_operand" "w")
1388 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1389 "TARGET_VFP_FP16INST"
1390 "vfnms.f16\\t%0, %1, %2"
1391 [(set_attr "conds" "unconditional")
1392 (set_attr "type" "ffmas")]
1395 (define_insn "*fnmsub<SDF:mode>4"
1396 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1397 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1398 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1399 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1400 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1401 "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1402 [(set_attr "predicable" "yes")
1403 (set_attr "predicable_short_it" "no")
1404 (set_attr "type" "ffma<vfp_type>")]
1407 (define_insn "*fnmaddhf4"
1408 [(set (match_operand:HF 0 "register_operand" "=w")
1409 (fma:HF (neg:HF (match_operand:HF 1 "register_operand" "w"))
1410 (match_operand:HF 2 "register_operand" "w")
1411 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1412 "TARGET_VFP_FP16INST"
1413 "vfnma.f16\\t%0, %1, %2"
1414 [(set_attr "conds" "unconditional")
1415 (set_attr "type" "ffmas")]
1418 (define_insn "*fnmadd<SDF:mode>4"
1419 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1420 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1422 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1423 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1424 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1425 "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1426 [(set_attr "predicable" "yes")
1427 (set_attr "predicable_short_it" "no")
1428 (set_attr "type" "ffma<vfp_type>")]
1432 ;; Conversion routines
1434 (define_insn "*extendsfdf2_vfp"
1435 [(set (match_operand:DF 0 "s_register_operand" "=w")
1436 (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
1437 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1438 "vcvt%?.f64.f32\\t%P0, %1"
1439 [(set_attr "predicable" "yes")
1440 (set_attr "predicable_short_it" "no")
1441 (set_attr "type" "f_cvt")]
1444 (define_insn "*truncdfsf2_vfp"
1445 [(set (match_operand:SF 0 "s_register_operand" "=t")
1446 (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
1447 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1448 "vcvt%?.f32.f64\\t%0, %P1"
1449 [(set_attr "predicable" "yes")
1450 (set_attr "predicable_short_it" "no")
1451 (set_attr "type" "f_cvt")]
1454 (define_insn "extendhfsf2"
1455 [(set (match_operand:SF 0 "s_register_operand" "=t")
1456 (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))]
1457 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1458 "vcvtb%?.f32.f16\\t%0, %1"
1459 [(set_attr "predicable" "yes")
1460 (set_attr "predicable_short_it" "no")
1461 (set_attr "type" "f_cvt")]
1464 (define_insn "*truncdfhf2"
1465 [(set (match_operand:HF 0 "s_register_operand" "=t")
1466 (float_truncate:HF (match_operand:DF 1 "s_register_operand" "w")))]
1467 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1468 "vcvtb%?.f16.f64\\t%0, %P1"
1469 [(set_attr "predicable" "yes")
1470 (set_attr "predicable_short_it" "no")
1471 (set_attr "type" "f_cvt")]
1474 (define_insn "*extendhfdf2"
1475 [(set (match_operand:DF 0 "s_register_operand" "=w")
1476 (float_extend:DF (match_operand:HF 1 "s_register_operand" "t")))]
1477 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1478 "vcvtb%?.f64.f16\\t%P0, %1"
1479 [(set_attr "predicable" "yes")
1480 (set_attr "predicable_short_it" "no")
1481 (set_attr "type" "f_cvt")]
1484 (define_insn "truncsfhf2"
1485 [(set (match_operand:HF 0 "s_register_operand" "=t")
1486 (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
1487 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1488 "vcvtb%?.f16.f32\\t%0, %1"
1489 [(set_attr "predicable" "yes")
1490 (set_attr "predicable_short_it" "no")
1491 (set_attr "type" "f_cvt")]
1494 (define_insn "*truncsisf2_vfp"
1495 [(set (match_operand:SI 0 "s_register_operand" "=t")
1496 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1497 "TARGET_32BIT && TARGET_HARD_FLOAT"
1498 "vcvt%?.s32.f32\\t%0, %1"
1499 [(set_attr "predicable" "yes")
1500 (set_attr "predicable_short_it" "no")
1501 (set_attr "type" "f_cvtf2i")]
1504 (define_insn "*truncsidf2_vfp"
1505 [(set (match_operand:SI 0 "s_register_operand" "=t")
1506 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
1507 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1508 "vcvt%?.s32.f64\\t%0, %P1"
1509 [(set_attr "predicable" "yes")
1510 (set_attr "predicable_short_it" "no")
1511 (set_attr "type" "f_cvtf2i")]
1515 (define_insn "fixuns_truncsfsi2"
1516 [(set (match_operand:SI 0 "s_register_operand" "=t")
1517 (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1518 "TARGET_32BIT && TARGET_HARD_FLOAT"
1519 "vcvt%?.u32.f32\\t%0, %1"
1520 [(set_attr "predicable" "yes")
1521 (set_attr "predicable_short_it" "no")
1522 (set_attr "type" "f_cvtf2i")]
1525 (define_insn "fixuns_truncdfsi2"
1526 [(set (match_operand:SI 0 "s_register_operand" "=t")
1527 (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
1528 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1529 "vcvt%?.u32.f64\\t%0, %P1"
1530 [(set_attr "predicable" "yes")
1531 (set_attr "predicable_short_it" "no")
1532 (set_attr "type" "f_cvtf2i")]
1536 (define_insn "*floatsisf2_vfp"
1537 [(set (match_operand:SF 0 "s_register_operand" "=t")
1538 (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1539 "TARGET_32BIT && TARGET_HARD_FLOAT"
1540 "vcvt%?.f32.s32\\t%0, %1"
1541 [(set_attr "predicable" "yes")
1542 (set_attr "predicable_short_it" "no")
1543 (set_attr "type" "f_cvti2f")]
1546 (define_insn "*floatsidf2_vfp"
1547 [(set (match_operand:DF 0 "s_register_operand" "=w")
1548 (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1549 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1550 "vcvt%?.f64.s32\\t%P0, %1"
1551 [(set_attr "predicable" "yes")
1552 (set_attr "predicable_short_it" "no")
1553 (set_attr "type" "f_cvti2f")]
1557 (define_insn "floatunssisf2"
1558 [(set (match_operand:SF 0 "s_register_operand" "=t")
1559 (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1560 "TARGET_32BIT && TARGET_HARD_FLOAT"
1561 "vcvt%?.f32.u32\\t%0, %1"
1562 [(set_attr "predicable" "yes")
1563 (set_attr "predicable_short_it" "no")
1564 (set_attr "type" "f_cvti2f")]
1567 (define_insn "floatunssidf2"
1568 [(set (match_operand:DF 0 "s_register_operand" "=w")
1569 (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1570 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1571 "vcvt%?.f64.u32\\t%P0, %1"
1572 [(set_attr "predicable" "yes")
1573 (set_attr "predicable_short_it" "no")
1574 (set_attr "type" "f_cvti2f")]
1580 (define_insn "neon_vsqrthf"
1581 [(set (match_operand:HF 0 "s_register_operand" "=w")
1582 (sqrt:HF (match_operand:HF 1 "s_register_operand" "w")))]
1583 "TARGET_VFP_FP16INST"
1585 [(set_attr "conds" "unconditional")
1586 (set_attr "type" "fsqrts")]
1589 (define_insn "neon_vrsqrtshf"
1591 (match_operand:HF 0 "s_register_operand" "=w")
1592 (unspec:HF [(match_operand:HF 1 "s_register_operand" "w")
1593 (match_operand:HF 2 "s_register_operand" "w")]
1595 "TARGET_VFP_FP16INST"
1596 "vrsqrts.f16\t%0, %1, %2"
1597 [(set_attr "conds" "unconditional")
1598 (set_attr "type" "fsqrts")]
1601 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1602 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1604 (define_insn "*sqrtsf2_vfp"
1605 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1606 (sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))]
1607 "TARGET_32BIT && TARGET_HARD_FLOAT"
1608 "vsqrt%?.f32\\t%0, %1"
1609 [(set_attr "predicable" "yes")
1610 (set_attr "predicable_short_it" "no")
1611 (set_attr "arch" "*,armv6_or_vfpv3")
1612 (set_attr "type" "fsqrts")]
1615 (define_insn "*sqrtdf2_vfp"
1616 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1617 (sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))]
1618 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1619 "vsqrt%?.f64\\t%P0, %P1"
1620 [(set_attr "predicable" "yes")
1621 (set_attr "predicable_short_it" "no")
1622 (set_attr "arch" "*,armv6_or_vfpv3")
1623 (set_attr "type" "fsqrtd")]
1627 ;; Patterns to split/copy vfp condition flags.
1629 (define_insn "*movcc_vfp"
1630 [(set (reg CC_REGNUM)
1631 (reg VFPCC_REGNUM))]
1632 "TARGET_32BIT && TARGET_HARD_FLOAT"
1633 "vmrs%?\\tAPSR_nzcv, FPSCR"
1634 [(set_attr "conds" "set")
1635 (set_attr "type" "f_flag")]
1638 (define_insn_and_split "*cmpsf_split_vfp"
1639 [(set (reg:CCFP CC_REGNUM)
1640 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t")
1641 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1642 "TARGET_32BIT && TARGET_HARD_FLOAT"
1644 "TARGET_32BIT && TARGET_HARD_FLOAT"
1645 [(set (reg:CCFP VFPCC_REGNUM)
1646 (compare:CCFP (match_dup 0)
1648 (set (reg:CCFP CC_REGNUM)
1649 (reg:CCFP VFPCC_REGNUM))]
1653 (define_insn_and_split "*cmpsf_trap_split_vfp"
1654 [(set (reg:CCFPE CC_REGNUM)
1655 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t")
1656 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1657 "TARGET_32BIT && TARGET_HARD_FLOAT"
1659 "TARGET_32BIT && TARGET_HARD_FLOAT"
1660 [(set (reg:CCFPE VFPCC_REGNUM)
1661 (compare:CCFPE (match_dup 0)
1663 (set (reg:CCFPE CC_REGNUM)
1664 (reg:CCFPE VFPCC_REGNUM))]
1668 (define_insn_and_split "*cmpdf_split_vfp"
1669 [(set (reg:CCFP CC_REGNUM)
1670 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
1671 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1672 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1674 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1675 [(set (reg:CCFP VFPCC_REGNUM)
1676 (compare:CCFP (match_dup 0)
1678 (set (reg:CCFP CC_REGNUM)
1679 (reg:CCFP VFPCC_REGNUM))]
1683 (define_insn_and_split "*cmpdf_trap_split_vfp"
1684 [(set (reg:CCFPE CC_REGNUM)
1685 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
1686 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1687 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1689 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1690 [(set (reg:CCFPE VFPCC_REGNUM)
1691 (compare:CCFPE (match_dup 0)
1693 (set (reg:CCFPE CC_REGNUM)
1694 (reg:CCFPE VFPCC_REGNUM))]
1699 ;; Comparison patterns
1701 ;; In the compare with FP zero case the ARM Architecture Reference Manual
1702 ;; specifies the immediate to be #0.0. However, some buggy assemblers only
1703 ;; accept #0. We don't want to autodetect broken assemblers, so output #0.
1704 (define_insn "*cmpsf_vfp"
1705 [(set (reg:CCFP VFPCC_REGNUM)
1706 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t,t")
1707 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1708 "TARGET_32BIT && TARGET_HARD_FLOAT"
1711 vcmp%?.f32\\t%0, #0"
1712 [(set_attr "predicable" "yes")
1713 (set_attr "predicable_short_it" "no")
1714 (set_attr "type" "fcmps")]
1717 (define_insn "*cmpsf_trap_vfp"
1718 [(set (reg:CCFPE VFPCC_REGNUM)
1719 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t,t")
1720 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1721 "TARGET_32BIT && TARGET_HARD_FLOAT"
1723 vcmpe%?.f32\\t%0, %1
1724 vcmpe%?.f32\\t%0, #0"
1725 [(set_attr "predicable" "yes")
1726 (set_attr "predicable_short_it" "no")
1727 (set_attr "type" "fcmps")]
1730 (define_insn "*cmpdf_vfp"
1731 [(set (reg:CCFP VFPCC_REGNUM)
1732 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
1733 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1734 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1736 vcmp%?.f64\\t%P0, %P1
1737 vcmp%?.f64\\t%P0, #0"
1738 [(set_attr "predicable" "yes")
1739 (set_attr "predicable_short_it" "no")
1740 (set_attr "type" "fcmpd")]
1743 (define_insn "*cmpdf_trap_vfp"
1744 [(set (reg:CCFPE VFPCC_REGNUM)
1745 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
1746 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1747 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1749 vcmpe%?.f64\\t%P0, %P1
1750 vcmpe%?.f64\\t%P0, #0"
1751 [(set_attr "predicable" "yes")
1752 (set_attr "predicable_short_it" "no")
1753 (set_attr "type" "fcmpd")]
1756 ;; Fixed point to floating point conversions.
1757 (define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1758 [(set (match_operand:SF 0 "s_register_operand" "=t")
1759 (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
1761 "const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1762 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1763 "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2"
1764 [(set_attr "predicable" "yes")
1765 (set_attr "predicable_short_it" "no")
1766 (set_attr "type" "f_cvti2f")]
1769 ;; Not the ideal way of implementing this. Ideally we would be able to split
1770 ;; this into a move to a DP register and then a vcvt.f64.i32
1771 (define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1772 [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1773 (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
1775 "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
1776 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
1777 && !TARGET_VFP_SINGLE"
1779 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1780 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1781 vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1782 [(set_attr "predicable" "yes")
1783 (set_attr "ce_count" "2")
1784 (set_attr "predicable_short_it" "no")
1785 (set_attr "type" "f_cvti2f")
1786 (set_attr "length" "8")]
1789 (define_insn "*combine_vcvtf2i"
1790 [(set (match_operand:SI 0 "s_register_operand" "=t")
1791 (fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0")
1793 "const_double_vcvt_power_of_two" "Dp")))))]
1794 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1795 "vcvt%?.s32.f32\\t%0, %1, %v2"
1796 [(set_attr "predicable" "yes")
1797 (set_attr "predicable_short_it" "no")
1798 (set_attr "type" "f_cvtf2i")]
1801 ;; FP16 conversions.
1802 (define_insn "neon_vcvth<sup>hf"
1803 [(set (match_operand:HF 0 "s_register_operand" "=w")
1805 [(match_operand:SI 1 "s_register_operand" "w")]
1807 "TARGET_VFP_FP16INST"
1808 "vcvt.f16.<sup>%#32\t%0, %1"
1809 [(set_attr "conds" "unconditional")
1810 (set_attr "type" "f_cvti2f")]
1813 (define_insn "neon_vcvth<sup>si"
1814 [(set (match_operand:SI 0 "s_register_operand" "=w")
1816 [(match_operand:HF 1 "s_register_operand" "w")]
1818 "TARGET_VFP_FP16INST"
1819 "vcvt.<sup>%#32.f16\t%0, %1"
1820 [(set_attr "conds" "unconditional")
1821 (set_attr "type" "f_cvtf2i")]
1824 ;; The neon_vcvth<sup>_nhf patterns are used to generate the instruction for the
1825 ;; vcvth_n_f16_<sup>32 arm_fp16 intrinsics. They are complicated by the
1826 ;; hardware requirement that the source and destination registers are the same
1827 ;; despite having different machine modes. The approach is to use a temporary
1828 ;; register for the conversion and move that to the correct destination.
1830 ;; Generate an unspec pattern for the intrinsic.
1831 (define_insn "neon_vcvth<sup>_nhf_unspec"
1833 (match_operand:SI 0 "s_register_operand" "=w")
1835 [(match_operand:SI 1 "s_register_operand" "0")
1836 (match_operand:SI 2 "immediate_operand" "i")]
1839 (match_operand:HF 3 "s_register_operand" "=w")
1840 (float_truncate:HF (float:SF (match_dup 0))))]
1841 "TARGET_VFP_FP16INST"
1843 arm_const_bounds (operands[2], 1, 33);
1844 return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1846 [(set_attr "conds" "unconditional")
1847 (set_attr "type" "f_cvti2f")]
1850 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1851 (define_expand "neon_vcvth<sup>_nhf"
1852 [(match_operand:HF 0 "s_register_operand")
1853 (unspec:HF [(match_operand:SI 1 "s_register_operand")
1854 (match_operand:SI 2 "immediate_operand")]
1856 "TARGET_VFP_FP16INST"
1858 rtx op1 = gen_reg_rtx (SImode);
1860 arm_const_bounds (operands[2], 1, 33);
1862 emit_move_insn (op1, operands[1]);
1863 emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2],
1868 ;; The neon_vcvth<sup>_nsi patterns are used to generate the instruction for the
1869 ;; vcvth_n_<sup>32_f16 arm_fp16 intrinsics. They have the same restrictions and
1870 ;; are implemented in the same way as the neon_vcvth<sup>_nhf patterns.
1872 ;; Generate an unspec pattern, constraining the registers.
1873 (define_insn "neon_vcvth<sup>_nsi_unspec"
1874 [(set (match_operand:SI 0 "s_register_operand" "=w")
1879 (match_operand:HF 1 "s_register_operand" "w"))))
1880 (match_operand:SI 2 "immediate_operand" "i")]
1882 "TARGET_VFP_FP16INST"
1884 arm_const_bounds (operands[2], 1, 33);
1885 return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1887 [(set_attr "conds" "unconditional")
1888 (set_attr "type" "f_cvtf2i")]
1891 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1892 (define_expand "neon_vcvth<sup>_nsi"
1893 [(match_operand:SI 0 "s_register_operand")
1895 [(match_operand:HF 1 "s_register_operand")
1896 (match_operand:SI 2 "immediate_operand")]
1898 "TARGET_VFP_FP16INST"
1900 rtx op1 = gen_reg_rtx (SImode);
1902 arm_const_bounds (operands[2], 1, 33);
1903 emit_insn (gen_neon_vcvth<sup>_nsi_unspec (op1, operands[1], operands[2]));
1904 emit_move_insn (operands[0], op1);
1908 (define_insn "neon_vcvt<vcvth_op>h<sup>si"
1910 (match_operand:SI 0 "s_register_operand" "=w")
1912 [(match_operand:HF 1 "s_register_operand" "w")]
1914 "TARGET_VFP_FP16INST"
1915 "vcvt<vcvth_op>.<sup>%#32.f16\t%0, %1"
1916 [(set_attr "conds" "unconditional")
1917 (set_attr "type" "f_cvtf2i")]
1920 ;; Store multiple insn used in function prologue.
1921 (define_insn "*push_multi_vfp"
1922 [(match_parallel 2 "multi_register_push"
1923 [(set (match_operand:BLK 0 "memory_operand" "=m")
1924 (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
1925 UNSPEC_PUSH_MULT))])]
1926 "TARGET_32BIT && TARGET_HARD_FLOAT"
1927 "* return vfp_output_vstmd (operands);"
1928 [(set_attr "type" "f_stored")]
1931 ;; VRINT round to integral instructions.
1932 ;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
1933 ;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
1934 ;; rintsf2, rintdf2.
1935 (define_insn "<vrint_pattern><SDF:mode>2"
1936 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1937 (unspec:SDF [(match_operand:SDF 1
1938 "register_operand" "<F_constraint>")]
1940 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1941 "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
1942 [(set_attr "predicable" "<vrint_predicable>")
1943 (set_attr "predicable_short_it" "no")
1944 (set_attr "type" "f_rint<vfp_type>")
1945 (set_attr "conds" "<vrint_conds>")]
1948 ;; Implements the lround, lfloor and lceil optabs.
1949 (define_insn "l<vrint_pattern><su_optab><mode>si2"
1950 [(set (match_operand:SI 0 "register_operand" "=t")
1951 (FIXUORS:SI (unspec:SDF
1952 [(match_operand:SDF 1
1953 "register_operand" "<F_constraint>")] VCVT)))]
1954 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1955 "vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1"
1956 [(set_attr "predicable" "no")
1957 (set_attr "conds" "unconditional")
1958 (set_attr "type" "f_cvtf2i")]
1961 ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
1962 ;; The 'smax' and 'smin' RTL standard pattern names do not specify which
1963 ;; operand will be returned when both operands are zero (i.e. they may not
1964 ;; honour signed zeroes), or when either operand is NaN. Therefore GCC
1965 ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
1968 (define_insn "smax<mode>3"
1969 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1970 (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1971 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1972 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1973 "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1974 [(set_attr "type" "f_minmax<vfp_type>")
1975 (set_attr "conds" "unconditional")]
1978 (define_insn "smin<mode>3"
1979 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1980 (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1981 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1982 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1983 "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1984 [(set_attr "type" "f_minmax<vfp_type>")
1985 (set_attr "conds" "unconditional")]
1988 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
1990 (define_insn "neon_<fmaxmin_op>hf"
1992 (match_operand:HF 0 "s_register_operand" "=w")
1994 [(match_operand:HF 1 "s_register_operand" "w")
1995 (match_operand:HF 2 "s_register_operand" "w")]
1997 "TARGET_VFP_FP16INST"
1998 "<fmaxmin_op>.f16\t%0, %1, %2"
1999 [(set_attr "conds" "unconditional")
2000 (set_attr "type" "f_minmaxs")]
2003 (define_insn "<fmaxmin><mode>3"
2004 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
2005 (unspec:SDF [(match_operand:SDF 1 "s_register_operand" "<F_constraint>")
2006 (match_operand:SDF 2 "s_register_operand" "<F_constraint>")]
2008 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2009 "<fmaxmin_op>.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2010 [(set_attr "type" "f_minmax<vfp_type>")
2011 (set_attr "conds" "unconditional")]
2014 ;; Write Floating-point Status and Control Register.
2015 (define_insn "set_fpscr"
2016 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)]
2018 "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
2019 [(set_attr "type" "mrs")])
2021 ;; Read Floating-point Status and Control Register.
2022 (define_insn "get_fpscr"
2023 [(set (match_operand:SI 0 "register_operand" "=r")
2024 (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
2026 "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
2027 [(set_attr "type" "mrs")])
2030 ;; Unimplemented insns:
2033 ;; fmdhr et al (VFPv1)
2034 ;; Support for xD (single precision only) variants.
2037 ;; Split an immediate DF move to two immediate SI moves.
2038 (define_insn_and_split "no_literal_pool_df_immediate"
2039 [(set (match_operand:DF 0 "s_register_operand" "")
2040 (match_operand:DF 1 "const_double_operand" ""))]
2041 "TARGET_THUMB2 && arm_disable_literal_pool
2042 && !(TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
2043 && vfp3_const_double_rtx (operands[1]))"
2045 "&& !reload_completed"
2046 [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
2047 (set (subreg:SI (match_dup 1) 4) (match_dup 3))
2048 (set (match_dup 0) (match_dup 1))]
2051 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
2052 operands[2] = GEN_INT ((int) buf[0]);
2053 operands[3] = GEN_INT ((int) buf[1]);
2054 operands[1] = gen_reg_rtx (DFmode);
2057 ;; Split an immediate SF move to one immediate SI move.
2058 (define_insn_and_split "no_literal_pool_sf_immediate"
2059 [(set (match_operand:SF 0 "s_register_operand" "")
2060 (match_operand:SF 1 "const_double_operand" ""))]
2061 "TARGET_THUMB2 && arm_disable_literal_pool
2062 && !(TARGET_HARD_FLOAT && vfp3_const_double_rtx (operands[1]))"
2064 "&& !reload_completed"
2065 [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
2066 (set (match_dup 0) (match_dup 1))]
2069 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
2070 operands[2] = GEN_INT ((int) buf);
2071 operands[1] = gen_reg_rtx (SFmode);