1 ;; ARM VFP instruction patterns
2 ;; Copyright (C) 2003-2018 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 "conds" "*, *, unconditional, *, unconditional, unconditional,\
414 unconditional, unconditional, unconditional,\
416 (set_attr "predicable" "yes, yes, no, yes, no, no, no, no, no, no")
417 (set_attr "predicable_short_it" "no, no, no, yes,\
420 (set_attr_alternative "type"
421 [(const_string "load_4") (const_string "store_4")
422 (const_string "fmov") (const_string "mov_reg")
423 (const_string "f_mcr") (const_string "f_mrc")
424 (const_string "fconsts") (const_string "neon_load1_1reg")
425 (const_string "neon_store1_1reg")
426 (if_then_else (match_test "arm_arch_thumb2")
427 (const_string "mov_imm")
428 (const_string "multiple"))])
429 (set_attr_alternative "length"
430 [(const_int 4) (const_int 4)
431 (const_int 4) (const_int 4)
432 (const_int 4) (const_int 4)
433 (const_int 4) (const_int 4)
435 (if_then_else (match_test "arm_arch_thumb2")
440 (define_insn "*movhf_vfp_neon"
441 [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r")
442 (match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))]
444 && TARGET_HARD_FLOAT && TARGET_NEON_FP16
445 && !TARGET_VFP_FP16INST
446 && ( s_register_operand (operands[0], HFmode)
447 || s_register_operand (operands[1], HFmode))"
449 switch (which_alternative)
451 case 0: /* S register from memory */
452 return \"vld1.16\\t{%z0}, %A1\";
453 case 1: /* memory from S register */
454 return \"vst1.16\\t{%z1}, %A0\";
455 case 2: /* ARM register from memory */
456 return \"ldrh\\t%0, %1\\t%@ __fp16\";
457 case 3: /* memory from ARM register */
458 return \"strh\\t%1, %0\\t%@ __fp16\";
459 case 4: /* S register from S register */
460 return \"vmov.f32\\t%0, %1\";
461 case 5: /* ARM register from ARM register */
462 return \"mov\\t%0, %1\\t%@ __fp16\";
463 case 6: /* S register from ARM register */
464 return \"vmov\\t%0, %1\";
465 case 7: /* ARM register from S register */
466 return \"vmov\\t%0, %1\";
467 case 8: /* ARM register from constant */
472 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
474 ops[0] = operands[0];
475 ops[1] = GEN_INT (bits);
476 ops[2] = GEN_INT (bits & 0xff00);
477 ops[3] = GEN_INT (bits & 0x00ff);
480 output_asm_insn (\"movw\\t%0, %1\", ops);
482 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
489 [(set_attr "conds" "unconditional")
490 (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\
491 load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
492 (set_attr "length" "4,4,4,4,4,4,4,4,8")]
495 ;; FP16 without element load/store instructions.
496 (define_insn "*movhf_vfp"
497 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
498 (match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))]
502 && !TARGET_VFP_FP16INST
503 && ( s_register_operand (operands[0], HFmode)
504 || s_register_operand (operands[1], HFmode))"
506 switch (which_alternative)
508 case 0: /* ARM register from memory */
509 return \"ldrh\\t%0, %1\\t%@ __fp16\";
510 case 1: /* memory from ARM register */
511 return \"strh\\t%1, %0\\t%@ __fp16\";
512 case 2: /* S register from S register */
513 return \"vmov.f32\\t%0, %1\";
514 case 3: /* ARM register from ARM register */
515 return \"mov\\t%0, %1\\t%@ __fp16\";
516 case 4: /* S register from ARM register */
517 return \"vmov\\t%0, %1\";
518 case 5: /* ARM register from S register */
519 return \"vmov\\t%0, %1\";
520 case 6: /* ARM register from constant */
525 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
527 ops[0] = operands[0];
528 ops[1] = GEN_INT (bits);
529 ops[2] = GEN_INT (bits & 0xff00);
530 ops[3] = GEN_INT (bits & 0x00ff);
533 output_asm_insn (\"movw\\t%0, %1\", ops);
535 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
542 [(set_attr "conds" "unconditional")
543 (set_attr "type" "load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
544 (set_attr "length" "4,4,4,4,4,4,8")]
549 ;; Disparage the w<->r cases because reloading an invalid address is
550 ;; preferable to loading the value via integer registers.
552 (define_insn "*movsf_vfp"
553 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t ,Uv,r ,m,t,r")
554 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
555 "TARGET_ARM && TARGET_HARD_FLOAT
556 && ( s_register_operand (operands[0], SFmode)
557 || s_register_operand (operands[1], SFmode))"
559 switch (which_alternative)
562 return \"vmov%?\\t%0, %1\";
564 return \"vmov%?\\t%0, %1\";
566 return \"vmov%?.f32\\t%0, %1\";
568 return output_move_vfp (operands);
570 return \"ldr%?\\t%0, %1\\t%@ float\";
572 return \"str%?\\t%1, %0\\t%@ float\";
574 return \"vmov%?.f32\\t%0, %1\";
576 return \"mov%?\\t%0, %1\\t%@ float\";
581 [(set_attr "predicable" "yes")
583 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
584 (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
585 (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
588 (define_insn "*thumb2_movsf_vfp"
589 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t ,Uv,r ,m,t,r")
590 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
591 "TARGET_THUMB2 && TARGET_HARD_FLOAT
592 && ( s_register_operand (operands[0], SFmode)
593 || s_register_operand (operands[1], SFmode))"
595 switch (which_alternative)
598 return \"vmov%?\\t%0, %1\";
600 return \"vmov%?\\t%0, %1\";
602 return \"vmov%?.f32\\t%0, %1\";
604 return output_move_vfp (operands);
606 return \"ldr%?\\t%0, %1\\t%@ float\";
608 return \"str%?\\t%1, %0\\t%@ float\";
610 return \"vmov%?.f32\\t%0, %1\";
612 return \"mov%?\\t%0, %1\\t%@ float\";
617 [(set_attr "predicable" "yes")
619 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
620 (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*")
621 (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
626 (define_insn "*movdf_vfp"
627 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r, m,w,r")
628 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,G,UvF,w ,mF,r,w,r"))]
629 "TARGET_ARM && TARGET_HARD_FLOAT
630 && ( register_operand (operands[0], DFmode)
631 || register_operand (operands[1], DFmode))"
634 switch (which_alternative)
637 return \"vmov%?\\t%P0, %Q1, %R1\";
639 return \"vmov%?\\t%Q0, %R0, %P1\";
641 gcc_assert (TARGET_VFP_DOUBLE);
642 return \"vmov%?.f64\\t%P0, %1\";
644 gcc_assert (TARGET_VFP_DOUBLE);
645 return \"vmov.i64\\t%P0, #0\\t%@ float\";
647 return output_move_vfp (operands);
649 return output_move_double (operands, true, NULL);
651 if (TARGET_VFP_SINGLE)
652 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
654 return \"vmov%?.f64\\t%P0, %P1\";
662 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,f_stored,\
663 load_8,store_8,ffarithd,multiple")
664 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
665 (eq_attr "alternative" "8")
667 (match_test "TARGET_VFP_SINGLE")
671 (set_attr "predicable" "yes,yes,yes,no,yes,yes,yes,yes,yes,yes")
672 (set_attr "pool_range" "*,*,*,*,1020,*,1020,*,*,*")
673 (set_attr "neg_pool_range" "*,*,*,*,1004,*,1004,*,*,*")
674 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
677 (define_insn "*thumb2_movdf_vfp"
678 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r ,m,w,r")
679 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,G,UvF,w, mF,r, w,r"))]
680 "TARGET_THUMB2 && TARGET_HARD_FLOAT
681 && ( register_operand (operands[0], DFmode)
682 || register_operand (operands[1], DFmode))"
685 switch (which_alternative)
688 return \"vmov%?\\t%P0, %Q1, %R1\";
690 return \"vmov%?\\t%Q0, %R0, %P1\";
692 gcc_assert (TARGET_VFP_DOUBLE);
693 return \"vmov%?.f64\\t%P0, %1\";
695 gcc_assert (TARGET_VFP_DOUBLE);
696 return \"vmov.i64\\t%P0, #0\\t%@ float\";
698 return output_move_vfp (operands);
699 case 6: case 7: case 9:
700 return output_move_double (operands, true, NULL);
702 if (TARGET_VFP_SINGLE)
703 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
705 return \"vmov%?.f64\\t%P0, %P1\";
711 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,\
712 f_stored,load_8,store_8,ffarithd,multiple")
713 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
714 (eq_attr "alternative" "8")
716 (match_test "TARGET_VFP_SINGLE")
720 (set_attr "pool_range" "*,*,*,*,1018,*,4094,*,*,*")
721 (set_attr "neg_pool_range" "*,*,*,*,1008,*,0,*,*,*")
722 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
726 ;; Conditional move patterns
728 (define_insn "*movsfcc_vfp"
729 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
731 (match_operator 3 "arm_comparison_operator"
732 [(match_operand 4 "cc_register" "") (const_int 0)])
733 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
734 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
735 "TARGET_ARM && TARGET_HARD_FLOAT"
739 vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
742 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
745 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
746 [(set_attr "conds" "use")
747 (set_attr "length" "4,4,8,4,4,8,4,4,8")
748 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
751 (define_insn "*thumb2_movsfcc_vfp"
752 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
754 (match_operator 3 "arm_comparison_operator"
755 [(match_operand 4 "cc_register" "") (const_int 0)])
756 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
757 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
758 "TARGET_THUMB2 && TARGET_HARD_FLOAT && !arm_restrict_it"
760 it\\t%D3\;vmov%D3.f32\\t%0, %2
761 it\\t%d3\;vmov%d3.f32\\t%0, %1
762 ite\\t%D3\;vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
763 it\\t%D3\;vmov%D3\\t%0, %2
764 it\\t%d3\;vmov%d3\\t%0, %1
765 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
766 it\\t%D3\;vmov%D3\\t%0, %2
767 it\\t%d3\;vmov%d3\\t%0, %1
768 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
769 [(set_attr "conds" "use")
770 (set_attr "length" "6,6,10,6,6,10,6,6,10")
771 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
774 (define_insn "*movdfcc_vfp"
775 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
777 (match_operator 3 "arm_comparison_operator"
778 [(match_operand 4 "cc_register" "") (const_int 0)])
779 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
780 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
781 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
783 vmov%D3.f64\\t%P0, %P2
784 vmov%d3.f64\\t%P0, %P1
785 vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
786 vmov%D3\\t%P0, %Q2, %R2
787 vmov%d3\\t%P0, %Q1, %R1
788 vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
789 vmov%D3\\t%Q0, %R0, %P2
790 vmov%d3\\t%Q0, %R0, %P1
791 vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
792 [(set_attr "conds" "use")
793 (set_attr "length" "4,4,8,4,4,8,4,4,8")
794 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcr,f_mrrc,f_mrrc,f_mrrc")]
797 (define_insn "*thumb2_movdfcc_vfp"
798 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
800 (match_operator 3 "arm_comparison_operator"
801 [(match_operand 4 "cc_register" "") (const_int 0)])
802 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
803 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
804 "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && !arm_restrict_it"
806 it\\t%D3\;vmov%D3.f64\\t%P0, %P2
807 it\\t%d3\;vmov%d3.f64\\t%P0, %P1
808 ite\\t%D3\;vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
809 it\t%D3\;vmov%D3\\t%P0, %Q2, %R2
810 it\t%d3\;vmov%d3\\t%P0, %Q1, %R1
811 ite\\t%D3\;vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
812 it\t%D3\;vmov%D3\\t%Q0, %R0, %P2
813 it\t%d3\;vmov%d3\\t%Q0, %R0, %P1
814 ite\\t%D3\;vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
815 [(set_attr "conds" "use")
816 (set_attr "length" "6,6,10,6,6,10,6,6,10")
817 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcrr,f_mrrc,f_mrrc,f_mrrc")]
821 ;; Sign manipulation functions
823 (define_insn "*abssf2_vfp"
824 [(set (match_operand:SF 0 "s_register_operand" "=t")
825 (abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
826 "TARGET_32BIT && TARGET_HARD_FLOAT"
827 "vabs%?.f32\\t%0, %1"
828 [(set_attr "predicable" "yes")
829 (set_attr "type" "ffariths")]
832 (define_insn "*absdf2_vfp"
833 [(set (match_operand:DF 0 "s_register_operand" "=w")
834 (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
835 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
836 "vabs%?.f64\\t%P0, %P1"
837 [(set_attr "predicable" "yes")
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 "type" "ffariths")]
852 (define_insn_and_split "*negdf2_vfp"
853 [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r")
854 (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
855 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
857 vneg%?.f64\\t%P0, %P1
860 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
861 && arm_general_register_operand (operands[0], DFmode)"
862 [(set (match_dup 0) (match_dup 1))]
864 if (REGNO (operands[0]) == REGNO (operands[1]))
866 operands[0] = gen_highpart (SImode, operands[0]);
867 operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
871 rtx in_hi, in_lo, out_hi, out_lo;
873 in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
874 GEN_INT (0x80000000));
875 in_lo = gen_lowpart (SImode, operands[1]);
876 out_hi = gen_highpart (SImode, operands[0]);
877 out_lo = gen_lowpart (SImode, operands[0]);
879 if (REGNO (in_lo) == REGNO (out_hi))
881 emit_insn (gen_rtx_SET (out_lo, in_lo));
882 operands[0] = out_hi;
887 emit_insn (gen_rtx_SET (out_hi, in_hi));
888 operands[0] = out_lo;
893 [(set_attr "predicable" "yes")
894 (set_attr "length" "4,4,8")
895 (set_attr "type" "ffarithd")]
898 ;; ABS and NEG for FP16.
899 (define_insn "<absneg_str>hf2"
900 [(set (match_operand:HF 0 "s_register_operand" "=w")
901 (ABSNEG:HF (match_operand:HF 1 "s_register_operand" "w")))]
902 "TARGET_VFP_FP16INST"
903 "v<absneg_str>.f16\t%0, %1"
904 [(set_attr "conds" "unconditional")
905 (set_attr "type" "ffariths")]
908 (define_expand "neon_vabshf"
910 (match_operand:HF 0 "s_register_operand")
911 (abs:HF (match_operand:HF 1 "s_register_operand")))]
912 "TARGET_VFP_FP16INST"
914 emit_insn (gen_abshf2 (operands[0], operands[1]));
919 (define_insn "neon_v<fp16_rnd_str>hf"
920 [(set (match_operand:HF 0 "s_register_operand" "=w")
922 [(match_operand:HF 1 "s_register_operand" "w")]
924 "TARGET_VFP_FP16INST"
925 "<fp16_rnd_insn>.f16\t%0, %1"
926 [(set_attr "conds" "unconditional")
927 (set_attr "type" "neon_fp_round_s")]
930 (define_insn "neon_vrndihf"
931 [(set (match_operand:HF 0 "s_register_operand" "=w")
933 [(match_operand:HF 1 "s_register_operand" "w")]
935 "TARGET_VFP_FP16INST"
937 [(set_attr "conds" "unconditional")
938 (set_attr "type" "neon_fp_round_s")]
943 (define_insn "addhf3"
945 (match_operand:HF 0 "s_register_operand" "=w")
947 (match_operand:HF 1 "s_register_operand" "w")
948 (match_operand:HF 2 "s_register_operand" "w")))]
949 "TARGET_VFP_FP16INST"
950 "vadd.f16\t%0, %1, %2"
951 [(set_attr "conds" "unconditional")
952 (set_attr "type" "fadds")]
955 (define_insn "*addsf3_vfp"
956 [(set (match_operand:SF 0 "s_register_operand" "=t")
957 (plus:SF (match_operand:SF 1 "s_register_operand" "t")
958 (match_operand:SF 2 "s_register_operand" "t")))]
959 "TARGET_32BIT && TARGET_HARD_FLOAT"
960 "vadd%?.f32\\t%0, %1, %2"
961 [(set_attr "predicable" "yes")
962 (set_attr "type" "fadds")]
965 (define_insn "*adddf3_vfp"
966 [(set (match_operand:DF 0 "s_register_operand" "=w")
967 (plus:DF (match_operand:DF 1 "s_register_operand" "w")
968 (match_operand:DF 2 "s_register_operand" "w")))]
969 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
970 "vadd%?.f64\\t%P0, %P1, %P2"
971 [(set_attr "predicable" "yes")
972 (set_attr "type" "faddd")]
975 (define_insn "subhf3"
977 (match_operand:HF 0 "s_register_operand" "=w")
979 (match_operand:HF 1 "s_register_operand" "w")
980 (match_operand:HF 2 "s_register_operand" "w")))]
981 "TARGET_VFP_FP16INST"
982 "vsub.f16\t%0, %1, %2"
983 [(set_attr "conds" "unconditional")
984 (set_attr "type" "fadds")]
987 (define_insn "*subsf3_vfp"
988 [(set (match_operand:SF 0 "s_register_operand" "=t")
989 (minus:SF (match_operand:SF 1 "s_register_operand" "t")
990 (match_operand:SF 2 "s_register_operand" "t")))]
991 "TARGET_32BIT && TARGET_HARD_FLOAT"
992 "vsub%?.f32\\t%0, %1, %2"
993 [(set_attr "predicable" "yes")
994 (set_attr "type" "fadds")]
997 (define_insn "*subdf3_vfp"
998 [(set (match_operand:DF 0 "s_register_operand" "=w")
999 (minus:DF (match_operand:DF 1 "s_register_operand" "w")
1000 (match_operand:DF 2 "s_register_operand" "w")))]
1001 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1002 "vsub%?.f64\\t%P0, %P1, %P2"
1003 [(set_attr "predicable" "yes")
1004 (set_attr "type" "faddd")]
1011 (define_insn "divhf3"
1013 (match_operand:HF 0 "s_register_operand" "=w")
1015 (match_operand:HF 1 "s_register_operand" "w")
1016 (match_operand:HF 2 "s_register_operand" "w")))]
1017 "TARGET_VFP_FP16INST"
1018 "vdiv.f16\t%0, %1, %2"
1019 [(set_attr "conds" "unconditional")
1020 (set_attr "type" "fdivs")]
1023 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1024 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1026 (define_insn "*divsf3_vfp"
1027 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1028 (div:SF (match_operand:SF 1 "s_register_operand" "t,t")
1029 (match_operand:SF 2 "s_register_operand" "t,t")))]
1030 "TARGET_32BIT && TARGET_HARD_FLOAT"
1031 "vdiv%?.f32\\t%0, %1, %2"
1032 [(set_attr "predicable" "yes")
1033 (set_attr "arch" "*,armv6_or_vfpv3")
1034 (set_attr "type" "fdivs")]
1037 (define_insn "*divdf3_vfp"
1038 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1039 (div:DF (match_operand:DF 1 "s_register_operand" "w,w")
1040 (match_operand:DF 2 "s_register_operand" "w,w")))]
1041 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1042 "vdiv%?.f64\\t%P0, %P1, %P2"
1043 [(set_attr "predicable" "yes")
1044 (set_attr "arch" "*,armv6_or_vfpv3")
1045 (set_attr "type" "fdivd")]
1049 ;; Multiplication insns
1051 (define_insn "mulhf3"
1053 (match_operand:HF 0 "s_register_operand" "=w")
1054 (mult:HF (match_operand:HF 1 "s_register_operand" "w")
1055 (match_operand:HF 2 "s_register_operand" "w")))]
1056 "TARGET_VFP_FP16INST"
1057 "vmul.f16\t%0, %1, %2"
1058 [(set_attr "conds" "unconditional")
1059 (set_attr "type" "fmuls")]
1062 (define_insn "*mulsf3_vfp"
1063 [(set (match_operand:SF 0 "s_register_operand" "=t")
1064 (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1065 (match_operand:SF 2 "s_register_operand" "t")))]
1066 "TARGET_32BIT && TARGET_HARD_FLOAT"
1067 "vmul%?.f32\\t%0, %1, %2"
1068 [(set_attr "predicable" "yes")
1069 (set_attr "type" "fmuls")]
1072 (define_insn "*muldf3_vfp"
1073 [(set (match_operand:DF 0 "s_register_operand" "=w")
1074 (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1075 (match_operand:DF 2 "s_register_operand" "w")))]
1076 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1077 "vmul%?.f64\\t%P0, %P1, %P2"
1078 [(set_attr "predicable" "yes")
1079 (set_attr "type" "fmuld")]
1082 (define_insn "*mulsf3neghf_vfp"
1083 [(set (match_operand:HF 0 "s_register_operand" "=t")
1084 (mult:HF (neg:HF (match_operand:HF 1 "s_register_operand" "t"))
1085 (match_operand:HF 2 "s_register_operand" "t")))]
1086 "TARGET_VFP_FP16INST && !flag_rounding_math"
1087 "vnmul.f16\\t%0, %1, %2"
1088 [(set_attr "conds" "unconditional")
1089 (set_attr "type" "fmuls")]
1092 (define_insn "*negmulhf3_vfp"
1093 [(set (match_operand:HF 0 "s_register_operand" "=t")
1094 (neg:HF (mult:HF (match_operand:HF 1 "s_register_operand" "t")
1095 (match_operand:HF 2 "s_register_operand" "t"))))]
1096 "TARGET_VFP_FP16INST"
1097 "vnmul.f16\\t%0, %1, %2"
1098 [(set_attr "conds" "unconditional")
1099 (set_attr "type" "fmuls")]
1102 (define_insn "*mulsf3negsf_vfp"
1103 [(set (match_operand:SF 0 "s_register_operand" "=t")
1104 (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
1105 (match_operand:SF 2 "s_register_operand" "t")))]
1106 "TARGET_32BIT && TARGET_HARD_FLOAT && !flag_rounding_math"
1107 "vnmul%?.f32\\t%0, %1, %2"
1108 [(set_attr "predicable" "yes")
1109 (set_attr "type" "fmuls")]
1112 (define_insn "*negmulsf3_vfp"
1113 [(set (match_operand:SF 0 "s_register_operand" "=t")
1114 (neg:SF (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1115 (match_operand:SF 2 "s_register_operand" "t"))))]
1116 "TARGET_32BIT && TARGET_HARD_FLOAT"
1117 "vnmul%?.f32\\t%0, %1, %2"
1118 [(set_attr "predicable" "yes")
1119 (set_attr "type" "fmuls")]
1122 (define_insn "*muldf3negdf_vfp"
1123 [(set (match_operand:DF 0 "s_register_operand" "=w")
1124 (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
1125 (match_operand:DF 2 "s_register_operand" "w")))]
1126 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
1127 && !flag_rounding_math"
1128 "vnmul%?.f64\\t%P0, %P1, %P2"
1129 [(set_attr "predicable" "yes")
1130 (set_attr "type" "fmuld")]
1133 (define_insn "*negmuldf3_vfp"
1134 [(set (match_operand:DF 0 "s_register_operand" "=w")
1135 (neg:DF (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1136 (match_operand:DF 2 "s_register_operand" "w"))))]
1137 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1138 "vnmul%?.f64\\t%P0, %P1, %P2"
1139 [(set_attr "predicable" "yes")
1140 (set_attr "type" "fmuld")]
1144 ;; Multiply-accumulate insns
1147 (define_insn "*mulsf3addhf_vfp"
1148 [(set (match_operand:HF 0 "s_register_operand" "=t")
1150 (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1151 (match_operand:HF 3 "s_register_operand" "t"))
1152 (match_operand:HF 1 "s_register_operand" "0")))]
1153 "TARGET_VFP_FP16INST"
1154 "vmla.f16\\t%0, %2, %3"
1155 [(set_attr "conds" "unconditional")
1156 (set_attr "type" "fmacs")]
1159 (define_insn "*mulsf3addsf_vfp"
1160 [(set (match_operand:SF 0 "s_register_operand" "=t")
1161 (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1162 (match_operand:SF 3 "s_register_operand" "t"))
1163 (match_operand:SF 1 "s_register_operand" "0")))]
1164 "TARGET_32BIT && TARGET_HARD_FLOAT"
1165 "vmla%?.f32\\t%0, %2, %3"
1166 [(set_attr "predicable" "yes")
1167 (set_attr "type" "fmacs")]
1170 (define_insn "*muldf3adddf_vfp"
1171 [(set (match_operand:DF 0 "s_register_operand" "=w")
1172 (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1173 (match_operand:DF 3 "s_register_operand" "w"))
1174 (match_operand:DF 1 "s_register_operand" "0")))]
1175 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1176 "vmla%?.f64\\t%P0, %P2, %P3"
1177 [(set_attr "predicable" "yes")
1178 (set_attr "type" "fmacd")]
1182 (define_insn "*mulhf3subhf_vfp"
1183 [(set (match_operand:HF 0 "s_register_operand" "=t")
1184 (minus:HF (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1185 (match_operand:HF 3 "s_register_operand" "t"))
1186 (match_operand:HF 1 "s_register_operand" "0")))]
1187 "TARGET_VFP_FP16INST"
1188 "vnmls.f16\\t%0, %2, %3"
1189 [(set_attr "conds" "unconditional")
1190 (set_attr "type" "fmacs")]
1193 (define_insn "*mulsf3subsf_vfp"
1194 [(set (match_operand:SF 0 "s_register_operand" "=t")
1195 (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1196 (match_operand:SF 3 "s_register_operand" "t"))
1197 (match_operand:SF 1 "s_register_operand" "0")))]
1198 "TARGET_32BIT && TARGET_HARD_FLOAT"
1199 "vnmls%?.f32\\t%0, %2, %3"
1200 [(set_attr "predicable" "yes")
1201 (set_attr "type" "fmacs")]
1204 (define_insn "*muldf3subdf_vfp"
1205 [(set (match_operand:DF 0 "s_register_operand" "=w")
1206 (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1207 (match_operand:DF 3 "s_register_operand" "w"))
1208 (match_operand:DF 1 "s_register_operand" "0")))]
1209 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1210 "vnmls%?.f64\\t%P0, %P2, %P3"
1211 [(set_attr "predicable" "yes")
1212 (set_attr "type" "fmacd")]
1216 (define_insn "*mulhf3neghfaddhf_vfp"
1217 [(set (match_operand:HF 0 "s_register_operand" "=t")
1218 (minus:HF (match_operand:HF 1 "s_register_operand" "0")
1219 (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1220 (match_operand:HF 3 "s_register_operand" "t"))))]
1221 "TARGET_VFP_FP16INST"
1222 "vmls.f16\\t%0, %2, %3"
1223 [(set_attr "conds" "unconditional")
1224 (set_attr "type" "fmacs")]
1227 (define_insn "*mulsf3negsfaddsf_vfp"
1228 [(set (match_operand:SF 0 "s_register_operand" "=t")
1229 (minus:SF (match_operand:SF 1 "s_register_operand" "0")
1230 (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1231 (match_operand:SF 3 "s_register_operand" "t"))))]
1232 "TARGET_32BIT && TARGET_HARD_FLOAT"
1233 "vmls%?.f32\\t%0, %2, %3"
1234 [(set_attr "predicable" "yes")
1235 (set_attr "type" "fmacs")]
1238 (define_insn "*fmuldf3negdfadddf_vfp"
1239 [(set (match_operand:DF 0 "s_register_operand" "=w")
1240 (minus:DF (match_operand:DF 1 "s_register_operand" "0")
1241 (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1242 (match_operand:DF 3 "s_register_operand" "w"))))]
1243 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1244 "vmls%?.f64\\t%P0, %P2, %P3"
1245 [(set_attr "predicable" "yes")
1246 (set_attr "type" "fmacd")]
1251 (define_insn "*mulhf3neghfsubhf_vfp"
1252 [(set (match_operand:HF 0 "s_register_operand" "=t")
1254 (neg:HF (match_operand:HF 2 "s_register_operand" "t"))
1255 (match_operand:HF 3 "s_register_operand" "t"))
1256 (match_operand:HF 1 "s_register_operand" "0")))]
1257 "TARGET_VFP_FP16INST"
1258 "vnmla.f16\\t%0, %2, %3"
1259 [(set_attr "conds" "unconditional")
1260 (set_attr "type" "fmacs")]
1263 (define_insn "*mulsf3negsfsubsf_vfp"
1264 [(set (match_operand:SF 0 "s_register_operand" "=t")
1266 (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
1267 (match_operand:SF 3 "s_register_operand" "t"))
1268 (match_operand:SF 1 "s_register_operand" "0")))]
1269 "TARGET_32BIT && TARGET_HARD_FLOAT"
1270 "vnmla%?.f32\\t%0, %2, %3"
1271 [(set_attr "predicable" "yes")
1272 (set_attr "type" "fmacs")]
1275 (define_insn "*muldf3negdfsubdf_vfp"
1276 [(set (match_operand:DF 0 "s_register_operand" "=w")
1278 (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
1279 (match_operand:DF 3 "s_register_operand" "w"))
1280 (match_operand:DF 1 "s_register_operand" "0")))]
1281 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1282 "vnmla%?.f64\\t%P0, %P2, %P3"
1283 [(set_attr "predicable" "yes")
1284 (set_attr "type" "fmacd")]
1287 ;; Fused-multiply-accumulate
1289 (define_insn "fmahf4"
1290 [(set (match_operand:HF 0 "register_operand" "=w")
1292 (match_operand:HF 1 "register_operand" "w")
1293 (match_operand:HF 2 "register_operand" "w")
1294 (match_operand:HF 3 "register_operand" "0")))]
1295 "TARGET_VFP_FP16INST"
1296 "vfma.f16\\t%0, %1, %2"
1297 [(set_attr "conds" "unconditional")
1298 (set_attr "type" "ffmas")]
1301 (define_expand "neon_vfmahf"
1302 [(match_operand:HF 0 "s_register_operand")
1303 (match_operand:HF 1 "s_register_operand")
1304 (match_operand:HF 2 "s_register_operand")
1305 (match_operand:HF 3 "s_register_operand")]
1306 "TARGET_VFP_FP16INST"
1308 emit_insn (gen_fmahf4 (operands[0], operands[2], operands[3],
1313 (define_insn "fma<SDF:mode>4"
1314 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1315 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1316 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1317 (match_operand:SDF 3 "register_operand" "0")))]
1318 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1319 "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1320 [(set_attr "predicable" "yes")
1321 (set_attr "type" "ffma<vfp_type>")]
1324 (define_insn "fmsubhf4_fp16"
1325 [(set (match_operand:HF 0 "register_operand" "=w")
1327 (neg:HF (match_operand:HF 1 "register_operand" "w"))
1328 (match_operand:HF 2 "register_operand" "w")
1329 (match_operand:HF 3 "register_operand" "0")))]
1330 "TARGET_VFP_FP16INST"
1331 "vfms.f16\\t%0, %1, %2"
1332 [(set_attr "conds" "unconditional")
1333 (set_attr "type" "ffmas")]
1336 (define_expand "neon_vfmshf"
1337 [(match_operand:HF 0 "s_register_operand")
1338 (match_operand:HF 1 "s_register_operand")
1339 (match_operand:HF 2 "s_register_operand")
1340 (match_operand:HF 3 "s_register_operand")]
1341 "TARGET_VFP_FP16INST"
1343 emit_insn (gen_fmsubhf4_fp16 (operands[0], operands[2], operands[3],
1348 (define_insn "*fmsub<SDF:mode>4"
1349 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1350 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1352 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1353 (match_operand:SDF 3 "register_operand" "0")))]
1354 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1355 "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1356 [(set_attr "predicable" "yes")
1357 (set_attr "type" "ffma<vfp_type>")]
1360 (define_insn "*fnmsubhf4"
1361 [(set (match_operand:HF 0 "register_operand" "=w")
1362 (fma:HF (match_operand:HF 1 "register_operand" "w")
1363 (match_operand:HF 2 "register_operand" "w")
1364 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1365 "TARGET_VFP_FP16INST"
1366 "vfnms.f16\\t%0, %1, %2"
1367 [(set_attr "conds" "unconditional")
1368 (set_attr "type" "ffmas")]
1371 (define_insn "*fnmsub<SDF:mode>4"
1372 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1373 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1374 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1375 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1376 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1377 "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1378 [(set_attr "predicable" "yes")
1379 (set_attr "type" "ffma<vfp_type>")]
1382 (define_insn "*fnmaddhf4"
1383 [(set (match_operand:HF 0 "register_operand" "=w")
1384 (fma:HF (neg:HF (match_operand:HF 1 "register_operand" "w"))
1385 (match_operand:HF 2 "register_operand" "w")
1386 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1387 "TARGET_VFP_FP16INST"
1388 "vfnma.f16\\t%0, %1, %2"
1389 [(set_attr "conds" "unconditional")
1390 (set_attr "type" "ffmas")]
1393 (define_insn "*fnmadd<SDF:mode>4"
1394 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1395 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1397 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1398 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1399 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1400 "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1401 [(set_attr "predicable" "yes")
1402 (set_attr "type" "ffma<vfp_type>")]
1406 ;; Conversion routines
1408 (define_insn "*extendsfdf2_vfp"
1409 [(set (match_operand:DF 0 "s_register_operand" "=w")
1410 (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
1411 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1412 "vcvt%?.f64.f32\\t%P0, %1"
1413 [(set_attr "predicable" "yes")
1414 (set_attr "type" "f_cvt")]
1417 (define_insn "*truncdfsf2_vfp"
1418 [(set (match_operand:SF 0 "s_register_operand" "=t")
1419 (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
1420 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1421 "vcvt%?.f32.f64\\t%0, %P1"
1422 [(set_attr "predicable" "yes")
1423 (set_attr "type" "f_cvt")]
1426 (define_insn "extendhfsf2"
1427 [(set (match_operand:SF 0 "s_register_operand" "=t")
1428 (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))]
1429 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1430 "vcvtb%?.f32.f16\\t%0, %1"
1431 [(set_attr "predicable" "yes")
1432 (set_attr "type" "f_cvt")]
1435 (define_insn "*truncdfhf2"
1436 [(set (match_operand:HF 0 "s_register_operand" "=t")
1437 (float_truncate:HF (match_operand:DF 1 "s_register_operand" "w")))]
1438 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1439 "vcvtb%?.f16.f64\\t%0, %P1"
1440 [(set_attr "predicable" "yes")
1441 (set_attr "type" "f_cvt")]
1444 (define_insn "*extendhfdf2"
1445 [(set (match_operand:DF 0 "s_register_operand" "=w")
1446 (float_extend:DF (match_operand:HF 1 "s_register_operand" "t")))]
1447 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1448 "vcvtb%?.f64.f16\\t%P0, %1"
1449 [(set_attr "predicable" "yes")
1450 (set_attr "type" "f_cvt")]
1453 (define_insn "truncsfhf2"
1454 [(set (match_operand:HF 0 "s_register_operand" "=t")
1455 (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
1456 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1457 "vcvtb%?.f16.f32\\t%0, %1"
1458 [(set_attr "predicable" "yes")
1459 (set_attr "type" "f_cvt")]
1462 (define_insn "*truncsisf2_vfp"
1463 [(set (match_operand:SI 0 "s_register_operand" "=t")
1464 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1465 "TARGET_32BIT && TARGET_HARD_FLOAT"
1466 "vcvt%?.s32.f32\\t%0, %1"
1467 [(set_attr "predicable" "yes")
1468 (set_attr "type" "f_cvtf2i")]
1471 (define_insn "*truncsidf2_vfp"
1472 [(set (match_operand:SI 0 "s_register_operand" "=t")
1473 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
1474 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1475 "vcvt%?.s32.f64\\t%0, %P1"
1476 [(set_attr "predicable" "yes")
1477 (set_attr "type" "f_cvtf2i")]
1481 (define_insn "fixuns_truncsfsi2"
1482 [(set (match_operand:SI 0 "s_register_operand" "=t")
1483 (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1484 "TARGET_32BIT && TARGET_HARD_FLOAT"
1485 "vcvt%?.u32.f32\\t%0, %1"
1486 [(set_attr "predicable" "yes")
1487 (set_attr "type" "f_cvtf2i")]
1490 (define_insn "fixuns_truncdfsi2"
1491 [(set (match_operand:SI 0 "s_register_operand" "=t")
1492 (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
1493 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1494 "vcvt%?.u32.f64\\t%0, %P1"
1495 [(set_attr "predicable" "yes")
1496 (set_attr "type" "f_cvtf2i")]
1500 (define_insn "*floatsisf2_vfp"
1501 [(set (match_operand:SF 0 "s_register_operand" "=t")
1502 (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1503 "TARGET_32BIT && TARGET_HARD_FLOAT"
1504 "vcvt%?.f32.s32\\t%0, %1"
1505 [(set_attr "predicable" "yes")
1506 (set_attr "type" "f_cvti2f")]
1509 (define_insn "*floatsidf2_vfp"
1510 [(set (match_operand:DF 0 "s_register_operand" "=w")
1511 (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1512 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1513 "vcvt%?.f64.s32\\t%P0, %1"
1514 [(set_attr "predicable" "yes")
1515 (set_attr "type" "f_cvti2f")]
1519 (define_insn "floatunssisf2"
1520 [(set (match_operand:SF 0 "s_register_operand" "=t")
1521 (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1522 "TARGET_32BIT && TARGET_HARD_FLOAT"
1523 "vcvt%?.f32.u32\\t%0, %1"
1524 [(set_attr "predicable" "yes")
1525 (set_attr "type" "f_cvti2f")]
1528 (define_insn "floatunssidf2"
1529 [(set (match_operand:DF 0 "s_register_operand" "=w")
1530 (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1531 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1532 "vcvt%?.f64.u32\\t%P0, %1"
1533 [(set_attr "predicable" "yes")
1534 (set_attr "type" "f_cvti2f")]
1540 (define_insn "neon_vsqrthf"
1541 [(set (match_operand:HF 0 "s_register_operand" "=w")
1542 (sqrt:HF (match_operand:HF 1 "s_register_operand" "w")))]
1543 "TARGET_VFP_FP16INST"
1545 [(set_attr "conds" "unconditional")
1546 (set_attr "type" "fsqrts")]
1549 (define_insn "neon_vrsqrtshf"
1551 (match_operand:HF 0 "s_register_operand" "=w")
1552 (unspec:HF [(match_operand:HF 1 "s_register_operand" "w")
1553 (match_operand:HF 2 "s_register_operand" "w")]
1555 "TARGET_VFP_FP16INST"
1556 "vrsqrts.f16\t%0, %1, %2"
1557 [(set_attr "conds" "unconditional")
1558 (set_attr "type" "fsqrts")]
1561 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1562 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1564 (define_insn "*sqrtsf2_vfp"
1565 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1566 (sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))]
1567 "TARGET_32BIT && TARGET_HARD_FLOAT"
1568 "vsqrt%?.f32\\t%0, %1"
1569 [(set_attr "predicable" "yes")
1570 (set_attr "arch" "*,armv6_or_vfpv3")
1571 (set_attr "type" "fsqrts")]
1574 (define_insn "*sqrtdf2_vfp"
1575 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1576 (sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))]
1577 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1578 "vsqrt%?.f64\\t%P0, %P1"
1579 [(set_attr "predicable" "yes")
1580 (set_attr "arch" "*,armv6_or_vfpv3")
1581 (set_attr "type" "fsqrtd")]
1585 ;; Patterns to split/copy vfp condition flags.
1587 (define_insn "*movcc_vfp"
1588 [(set (reg CC_REGNUM)
1589 (reg VFPCC_REGNUM))]
1590 "TARGET_32BIT && TARGET_HARD_FLOAT"
1591 "vmrs%?\\tAPSR_nzcv, FPSCR"
1592 [(set_attr "conds" "set")
1593 (set_attr "type" "f_flag")]
1596 (define_insn_and_split "*cmpsf_split_vfp"
1597 [(set (reg:CCFP CC_REGNUM)
1598 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t")
1599 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1600 "TARGET_32BIT && TARGET_HARD_FLOAT"
1602 "TARGET_32BIT && TARGET_HARD_FLOAT"
1603 [(set (reg:CCFP VFPCC_REGNUM)
1604 (compare:CCFP (match_dup 0)
1606 (set (reg:CCFP CC_REGNUM)
1607 (reg:CCFP VFPCC_REGNUM))]
1611 (define_insn_and_split "*cmpsf_trap_split_vfp"
1612 [(set (reg:CCFPE CC_REGNUM)
1613 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t")
1614 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1615 "TARGET_32BIT && TARGET_HARD_FLOAT"
1617 "TARGET_32BIT && TARGET_HARD_FLOAT"
1618 [(set (reg:CCFPE VFPCC_REGNUM)
1619 (compare:CCFPE (match_dup 0)
1621 (set (reg:CCFPE CC_REGNUM)
1622 (reg:CCFPE VFPCC_REGNUM))]
1626 (define_insn_and_split "*cmpdf_split_vfp"
1627 [(set (reg:CCFP CC_REGNUM)
1628 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
1629 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1630 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1632 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1633 [(set (reg:CCFP VFPCC_REGNUM)
1634 (compare:CCFP (match_dup 0)
1636 (set (reg:CCFP CC_REGNUM)
1637 (reg:CCFP VFPCC_REGNUM))]
1641 (define_insn_and_split "*cmpdf_trap_split_vfp"
1642 [(set (reg:CCFPE CC_REGNUM)
1643 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
1644 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1645 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1647 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1648 [(set (reg:CCFPE VFPCC_REGNUM)
1649 (compare:CCFPE (match_dup 0)
1651 (set (reg:CCFPE CC_REGNUM)
1652 (reg:CCFPE VFPCC_REGNUM))]
1657 ;; Comparison patterns
1659 ;; In the compare with FP zero case the ARM Architecture Reference Manual
1660 ;; specifies the immediate to be #0.0. However, some buggy assemblers only
1661 ;; accept #0. We don't want to autodetect broken assemblers, so output #0.
1662 (define_insn "*cmpsf_vfp"
1663 [(set (reg:CCFP VFPCC_REGNUM)
1664 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t,t")
1665 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1666 "TARGET_32BIT && TARGET_HARD_FLOAT"
1669 vcmp%?.f32\\t%0, #0"
1670 [(set_attr "predicable" "yes")
1671 (set_attr "type" "fcmps")]
1674 (define_insn "*cmpsf_trap_vfp"
1675 [(set (reg:CCFPE VFPCC_REGNUM)
1676 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t,t")
1677 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1678 "TARGET_32BIT && TARGET_HARD_FLOAT"
1680 vcmpe%?.f32\\t%0, %1
1681 vcmpe%?.f32\\t%0, #0"
1682 [(set_attr "predicable" "yes")
1683 (set_attr "type" "fcmps")]
1686 (define_insn "*cmpdf_vfp"
1687 [(set (reg:CCFP VFPCC_REGNUM)
1688 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
1689 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1690 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1692 vcmp%?.f64\\t%P0, %P1
1693 vcmp%?.f64\\t%P0, #0"
1694 [(set_attr "predicable" "yes")
1695 (set_attr "type" "fcmpd")]
1698 (define_insn "*cmpdf_trap_vfp"
1699 [(set (reg:CCFPE VFPCC_REGNUM)
1700 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
1701 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1702 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1704 vcmpe%?.f64\\t%P0, %P1
1705 vcmpe%?.f64\\t%P0, #0"
1706 [(set_attr "predicable" "yes")
1707 (set_attr "type" "fcmpd")]
1710 ;; Fixed point to floating point conversions.
1711 (define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1712 [(set (match_operand:SF 0 "s_register_operand" "=t")
1713 (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
1715 "const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1716 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1717 "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2"
1718 [(set_attr "predicable" "yes")
1719 (set_attr "type" "f_cvti2f")]
1722 ;; Not the ideal way of implementing this. Ideally we would be able to split
1723 ;; this into a move to a DP register and then a vcvt.f64.i32
1724 (define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1725 [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1726 (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
1728 "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
1729 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
1730 && !TARGET_VFP_SINGLE"
1732 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1733 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1734 vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1735 [(set_attr "predicable" "yes")
1736 (set_attr "ce_count" "2")
1737 (set_attr "type" "f_cvti2f")
1738 (set_attr "length" "8")]
1741 (define_insn "*combine_vcvtf2i"
1742 [(set (match_operand:SI 0 "s_register_operand" "=t")
1743 (fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0")
1745 "const_double_vcvt_power_of_two" "Dp")))))]
1746 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1747 "vcvt%?.s32.f32\\t%0, %1, %v2"
1748 [(set_attr "predicable" "yes")
1749 (set_attr "type" "f_cvtf2i")]
1752 ;; FP16 conversions.
1753 (define_insn "neon_vcvth<sup>hf"
1754 [(set (match_operand:HF 0 "s_register_operand" "=w")
1756 [(match_operand:SI 1 "s_register_operand" "w")]
1758 "TARGET_VFP_FP16INST"
1759 "vcvt.f16.<sup>%#32\t%0, %1"
1760 [(set_attr "conds" "unconditional")
1761 (set_attr "type" "f_cvti2f")]
1764 (define_insn "neon_vcvth<sup>si"
1765 [(set (match_operand:SI 0 "s_register_operand" "=w")
1767 [(match_operand:HF 1 "s_register_operand" "w")]
1769 "TARGET_VFP_FP16INST"
1770 "vcvt.<sup>%#32.f16\t%0, %1"
1771 [(set_attr "conds" "unconditional")
1772 (set_attr "type" "f_cvtf2i")]
1775 ;; The neon_vcvth<sup>_nhf patterns are used to generate the instruction for the
1776 ;; vcvth_n_f16_<sup>32 arm_fp16 intrinsics. They are complicated by the
1777 ;; hardware requirement that the source and destination registers are the same
1778 ;; despite having different machine modes. The approach is to use a temporary
1779 ;; register for the conversion and move that to the correct destination.
1781 ;; Generate an unspec pattern for the intrinsic.
1782 (define_insn "neon_vcvth<sup>_nhf_unspec"
1784 (match_operand:SI 0 "s_register_operand" "=w")
1786 [(match_operand:SI 1 "s_register_operand" "0")
1787 (match_operand:SI 2 "immediate_operand" "i")]
1790 (match_operand:HF 3 "s_register_operand" "=w")
1791 (float_truncate:HF (float:SF (match_dup 0))))]
1792 "TARGET_VFP_FP16INST"
1794 arm_const_bounds (operands[2], 1, 33);
1795 return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1797 [(set_attr "conds" "unconditional")
1798 (set_attr "type" "f_cvti2f")]
1801 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1802 (define_expand "neon_vcvth<sup>_nhf"
1803 [(match_operand:HF 0 "s_register_operand")
1804 (unspec:HF [(match_operand:SI 1 "s_register_operand")
1805 (match_operand:SI 2 "immediate_operand")]
1807 "TARGET_VFP_FP16INST"
1809 rtx op1 = gen_reg_rtx (SImode);
1811 arm_const_bounds (operands[2], 1, 33);
1813 emit_move_insn (op1, operands[1]);
1814 emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2],
1819 ;; The neon_vcvth<sup>_nsi patterns are used to generate the instruction for the
1820 ;; vcvth_n_<sup>32_f16 arm_fp16 intrinsics. They have the same restrictions and
1821 ;; are implemented in the same way as the neon_vcvth<sup>_nhf patterns.
1823 ;; Generate an unspec pattern, constraining the registers.
1824 (define_insn "neon_vcvth<sup>_nsi_unspec"
1825 [(set (match_operand:SI 0 "s_register_operand" "=w")
1830 (match_operand:HF 1 "s_register_operand" "w"))))
1831 (match_operand:SI 2 "immediate_operand" "i")]
1833 "TARGET_VFP_FP16INST"
1835 arm_const_bounds (operands[2], 1, 33);
1836 return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1838 [(set_attr "conds" "unconditional")
1839 (set_attr "type" "f_cvtf2i")]
1842 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1843 (define_expand "neon_vcvth<sup>_nsi"
1844 [(match_operand:SI 0 "s_register_operand")
1846 [(match_operand:HF 1 "s_register_operand")
1847 (match_operand:SI 2 "immediate_operand")]
1849 "TARGET_VFP_FP16INST"
1851 rtx op1 = gen_reg_rtx (SImode);
1853 arm_const_bounds (operands[2], 1, 33);
1854 emit_insn (gen_neon_vcvth<sup>_nsi_unspec (op1, operands[1], operands[2]));
1855 emit_move_insn (operands[0], op1);
1859 (define_insn "neon_vcvt<vcvth_op>h<sup>si"
1861 (match_operand:SI 0 "s_register_operand" "=w")
1863 [(match_operand:HF 1 "s_register_operand" "w")]
1865 "TARGET_VFP_FP16INST"
1866 "vcvt<vcvth_op>.<sup>%#32.f16\t%0, %1"
1867 [(set_attr "conds" "unconditional")
1868 (set_attr "type" "f_cvtf2i")]
1871 ;; Store multiple insn used in function prologue.
1872 (define_insn "*push_multi_vfp"
1873 [(match_parallel 2 "multi_register_push"
1874 [(set (match_operand:BLK 0 "memory_operand" "=m")
1875 (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
1876 UNSPEC_PUSH_MULT))])]
1877 "TARGET_32BIT && TARGET_HARD_FLOAT"
1878 "* return vfp_output_vstmd (operands);"
1879 [(set_attr "type" "f_stored")]
1882 ;; VRINT round to integral instructions.
1883 ;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
1884 ;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
1885 ;; rintsf2, rintdf2.
1886 (define_insn "<vrint_pattern><SDF:mode>2"
1887 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1888 (unspec:SDF [(match_operand:SDF 1
1889 "register_operand" "<F_constraint>")]
1891 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1892 "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
1893 [(set_attr "predicable" "<vrint_predicable>")
1894 (set_attr "type" "f_rint<vfp_type>")
1895 (set_attr "conds" "<vrint_conds>")]
1898 ;; Implements the lround, lfloor and lceil optabs.
1899 (define_insn "l<vrint_pattern><su_optab><mode>si2"
1900 [(set (match_operand:SI 0 "register_operand" "=t")
1901 (FIXUORS:SI (unspec:SDF
1902 [(match_operand:SDF 1
1903 "register_operand" "<F_constraint>")] VCVT)))]
1904 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1905 "vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1"
1906 [(set_attr "conds" "unconditional")
1907 (set_attr "type" "f_cvtf2i")]
1910 ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
1911 ;; The 'smax' and 'smin' RTL standard pattern names do not specify which
1912 ;; operand will be returned when both operands are zero (i.e. they may not
1913 ;; honour signed zeroes), or when either operand is NaN. Therefore GCC
1914 ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
1917 (define_insn "smax<mode>3"
1918 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1919 (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1920 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1921 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1922 "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1923 [(set_attr "type" "f_minmax<vfp_type>")
1924 (set_attr "conds" "unconditional")]
1927 (define_insn "smin<mode>3"
1928 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1929 (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1930 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1931 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1932 "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1933 [(set_attr "type" "f_minmax<vfp_type>")
1934 (set_attr "conds" "unconditional")]
1937 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
1939 (define_insn "neon_<fmaxmin_op>hf"
1941 (match_operand:HF 0 "s_register_operand" "=w")
1943 [(match_operand:HF 1 "s_register_operand" "w")
1944 (match_operand:HF 2 "s_register_operand" "w")]
1946 "TARGET_VFP_FP16INST"
1947 "<fmaxmin_op>.f16\t%0, %1, %2"
1948 [(set_attr "conds" "unconditional")
1949 (set_attr "type" "f_minmaxs")]
1952 (define_insn "<fmaxmin><mode>3"
1953 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
1954 (unspec:SDF [(match_operand:SDF 1 "s_register_operand" "<F_constraint>")
1955 (match_operand:SDF 2 "s_register_operand" "<F_constraint>")]
1957 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1958 "<fmaxmin_op>.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1959 [(set_attr "type" "f_minmax<vfp_type>")
1960 (set_attr "conds" "unconditional")]
1963 ;; Write Floating-point Status and Control Register.
1964 (define_insn "set_fpscr"
1965 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)]
1967 "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
1968 [(set_attr "type" "mrs")])
1970 ;; Read Floating-point Status and Control Register.
1971 (define_insn "get_fpscr"
1972 [(set (match_operand:SI 0 "register_operand" "=r")
1973 (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
1975 "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
1976 [(set_attr "type" "mrs")])
1979 ;; Unimplemented insns:
1982 ;; fmdhr et al (VFPv1)
1983 ;; Support for xD (single precision only) variants.
1986 ;; Split an immediate DF move to two immediate SI moves.
1987 (define_insn_and_split "no_literal_pool_df_immediate"
1988 [(set (match_operand:DF 0 "s_register_operand" "")
1989 (match_operand:DF 1 "const_double_operand" ""))]
1990 "TARGET_THUMB2 && arm_disable_literal_pool
1991 && !(TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
1992 && vfp3_const_double_rtx (operands[1]))"
1994 "&& !reload_completed"
1995 [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
1996 (set (subreg:SI (match_dup 1) 4) (match_dup 3))
1997 (set (match_dup 0) (match_dup 1))]
2000 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
2001 operands[2] = GEN_INT ((int) buf[0]);
2002 operands[3] = GEN_INT ((int) buf[1]);
2003 operands[1] = gen_reg_rtx (DFmode);
2006 ;; Split an immediate SF move to one immediate SI move.
2007 (define_insn_and_split "no_literal_pool_sf_immediate"
2008 [(set (match_operand:SF 0 "s_register_operand" "")
2009 (match_operand:SF 1 "const_double_operand" ""))]
2010 "TARGET_THUMB2 && arm_disable_literal_pool
2011 && !(TARGET_HARD_FLOAT && vfp3_const_double_rtx (operands[1]))"
2013 "&& !reload_completed"
2014 [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
2015 (set (match_dup 0) (match_dup 1))]
2018 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
2019 operands[2] = GEN_INT ((int) buf);
2020 operands[1] = gen_reg_rtx (SFmode);