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 "store1")
64 (const_string "load1")
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, store1, load1,\
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 "store1")
160 (const_string "load1")
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, store1, load1,\
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,load1,store1,
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,load1,load1,store1,store1,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 && arm_tune != TARGET_CPU_cortexa8
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,load2,load2,store2,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored")
342 (set (attr "length") (cond [(eq_attr "alternative" "1,4,5,6") (const_int 8)
343 (eq_attr "alternative" "2") (const_int 12)
344 (eq_attr "alternative" "3") (const_int 16)
345 (eq_attr "alternative" "9")
347 (match_test "TARGET_VFP_SINGLE")
351 (set_attr "arm_pool_range" "*,*,*,*,1020,4096,*,*,*,*,1020,*")
352 (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
353 (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
354 (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
357 (define_insn "*movdi_vfp_cortexa8"
358 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,q,q,m,w,!r,w,w, Uv")
359 (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,q,r,w,w,Uvi,w"))]
360 "TARGET_32BIT && TARGET_HARD_FLOAT && arm_tune == TARGET_CPU_cortexa8
361 && ( register_operand (operands[0], DImode)
362 || register_operand (operands[1], DImode))
363 && !(TARGET_NEON && CONST_INT_P (operands[1])
364 && neon_immediate_valid_for_move (operands[1], DImode, NULL, NULL))"
366 switch (which_alternative)
376 return output_move_double (operands, true, NULL);
378 return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\";
380 return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\";
382 return \"vmov%?.f64\\t%P0, %P1\\t%@ int\";
384 return output_move_vfp (operands);
389 [(set_attr "type" "multiple,multiple,multiple,multiple,load2,load2,store2,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored")
390 (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8)
391 (eq_attr "alternative" "2") (const_int 12)
392 (eq_attr "alternative" "3") (const_int 16)
393 (eq_attr "alternative" "4,5,6")
395 "arm_count_output_move_double_insns (operands) \
398 (set_attr "predicable" "yes")
399 (set_attr "arm_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
400 (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
401 (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
402 (set (attr "ce_count")
403 (symbol_ref "get_attr_length (insn) / 4"))
404 (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
409 (define_insn "*movhf_vfp_fp16"
410 [(set (match_operand:HF 0 "nonimmediate_operand"
411 "= r,m,t,r,t,r,t,t,Um,r")
412 (match_operand:HF 1 "general_operand"
413 " m,r,t,r,r,t,Dv,Um,t,F"))]
415 && TARGET_VFP_FP16INST
416 && (s_register_operand (operands[0], HFmode)
417 || s_register_operand (operands[1], HFmode))"
419 switch (which_alternative)
421 case 0: /* ARM register from memory. */
422 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
423 case 1: /* Memory from ARM register. */
424 return \"strh%?\\t%1, %0\\t%@ __fp16\";
425 case 2: /* S register from S register. */
426 return \"vmov\\t%0, %1\t%@ __fp16\";
427 case 3: /* ARM register from ARM register. */
428 return \"mov%?\\t%0, %1\\t%@ __fp16\";
429 case 4: /* S register from ARM register. */
430 case 5: /* ARM register from S register. */
431 case 6: /* S register from immediate. */
432 return \"vmov.f16\\t%0, %1\t%@ __fp16\";
433 case 7: /* S register from memory. */
434 return \"vld1.16\\t{%z0}, %A1\";
435 case 8: /* Memory from S register. */
436 return \"vst1.16\\t{%z1}, %A0\";
437 case 9: /* ARM register from constant. */
442 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
444 ops[0] = operands[0];
445 ops[1] = GEN_INT (bits);
446 ops[2] = GEN_INT (bits & 0xff00);
447 ops[3] = GEN_INT (bits & 0x00ff);
450 output_asm_insn (\"movw\\t%0, %1\", ops);
452 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
459 [(set_attr "predicable" "yes, yes, no, yes, no, no, no, no, no, no")
460 (set_attr "predicable_short_it" "no, no, no, yes,\
463 (set_attr_alternative "type"
464 [(const_string "load1") (const_string "store1")
465 (const_string "fmov") (const_string "mov_reg")
466 (const_string "f_mcr") (const_string "f_mrc")
467 (const_string "fconsts") (const_string "neon_load1_1reg")
468 (const_string "neon_store1_1reg")
469 (if_then_else (match_test "arm_arch_thumb2")
470 (const_string "mov_imm")
471 (const_string "multiple"))])
472 (set_attr_alternative "length"
473 [(const_int 4) (const_int 4)
474 (const_int 4) (const_int 4)
475 (const_int 4) (const_int 4)
476 (const_int 4) (const_int 4)
478 (if_then_else (match_test "arm_arch_thumb2")
483 (define_insn "*movhf_vfp_neon"
484 [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r")
485 (match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))]
487 && TARGET_HARD_FLOAT && TARGET_NEON_FP16
488 && !TARGET_VFP_FP16INST
489 && ( s_register_operand (operands[0], HFmode)
490 || s_register_operand (operands[1], HFmode))"
492 switch (which_alternative)
494 case 0: /* S register from memory */
495 return \"vld1.16\\t{%z0}, %A1\";
496 case 1: /* memory from S register */
497 return \"vst1.16\\t{%z1}, %A0\";
498 case 2: /* ARM register from memory */
499 return \"ldrh\\t%0, %1\\t%@ __fp16\";
500 case 3: /* memory from ARM register */
501 return \"strh\\t%1, %0\\t%@ __fp16\";
502 case 4: /* S register from S register */
503 return \"vmov.f32\\t%0, %1\";
504 case 5: /* ARM register from ARM register */
505 return \"mov\\t%0, %1\\t%@ __fp16\";
506 case 6: /* S register from ARM register */
507 return \"vmov\\t%0, %1\";
508 case 7: /* ARM register from S register */
509 return \"vmov\\t%0, %1\";
510 case 8: /* ARM register from constant */
515 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
517 ops[0] = operands[0];
518 ops[1] = GEN_INT (bits);
519 ops[2] = GEN_INT (bits & 0xff00);
520 ops[3] = GEN_INT (bits & 0x00ff);
523 output_asm_insn (\"movw\\t%0, %1\", ops);
525 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
532 [(set_attr "conds" "unconditional")
533 (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\
534 load1,store1,fmov,mov_reg,f_mcr,f_mrc,multiple")
535 (set_attr "length" "4,4,4,4,4,4,4,4,8")]
538 ;; FP16 without element load/store instructions.
539 (define_insn "*movhf_vfp"
540 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
541 (match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))]
545 && !TARGET_VFP_FP16INST
546 && ( s_register_operand (operands[0], HFmode)
547 || s_register_operand (operands[1], HFmode))"
549 switch (which_alternative)
551 case 0: /* ARM register from memory */
552 return \"ldrh\\t%0, %1\\t%@ __fp16\";
553 case 1: /* memory from ARM register */
554 return \"strh\\t%1, %0\\t%@ __fp16\";
555 case 2: /* S register from S register */
556 return \"vmov.f32\\t%0, %1\";
557 case 3: /* ARM register from ARM register */
558 return \"mov\\t%0, %1\\t%@ __fp16\";
559 case 4: /* S register from ARM register */
560 return \"vmov\\t%0, %1\";
561 case 5: /* ARM register from S register */
562 return \"vmov\\t%0, %1\";
563 case 6: /* ARM register from constant */
568 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
570 ops[0] = operands[0];
571 ops[1] = GEN_INT (bits);
572 ops[2] = GEN_INT (bits & 0xff00);
573 ops[3] = GEN_INT (bits & 0x00ff);
576 output_asm_insn (\"movw\\t%0, %1\", ops);
578 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
585 [(set_attr "conds" "unconditional")
586 (set_attr "type" "load1,store1,fmov,mov_reg,f_mcr,f_mrc,multiple")
587 (set_attr "length" "4,4,4,4,4,4,8")]
592 ;; Disparage the w<->r cases because reloading an invalid address is
593 ;; preferable to loading the value via integer registers.
595 (define_insn "*movsf_vfp"
596 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t ,Uv,r ,m,t,r")
597 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
598 "TARGET_ARM && TARGET_HARD_FLOAT
599 && ( s_register_operand (operands[0], SFmode)
600 || s_register_operand (operands[1], SFmode))"
602 switch (which_alternative)
605 return \"vmov%?\\t%0, %1\";
607 return \"vmov%?\\t%0, %1\";
609 return \"vmov%?.f32\\t%0, %1\";
611 return output_move_vfp (operands);
613 return \"ldr%?\\t%0, %1\\t%@ float\";
615 return \"str%?\\t%1, %0\\t%@ float\";
617 return \"vmov%?.f32\\t%0, %1\";
619 return \"mov%?\\t%0, %1\\t%@ float\";
624 [(set_attr "predicable" "yes")
626 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load1,store1,fmov,mov_reg")
627 (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
628 (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
631 (define_insn "*thumb2_movsf_vfp"
632 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t ,Uv,r ,m,t,r")
633 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
634 "TARGET_THUMB2 && TARGET_HARD_FLOAT
635 && ( s_register_operand (operands[0], SFmode)
636 || s_register_operand (operands[1], SFmode))"
638 switch (which_alternative)
641 return \"vmov%?\\t%0, %1\";
643 return \"vmov%?\\t%0, %1\";
645 return \"vmov%?.f32\\t%0, %1\";
647 return output_move_vfp (operands);
649 return \"ldr%?\\t%0, %1\\t%@ float\";
651 return \"str%?\\t%1, %0\\t%@ float\";
653 return \"vmov%?.f32\\t%0, %1\";
655 return \"mov%?\\t%0, %1\\t%@ float\";
660 [(set_attr "predicable" "yes")
661 (set_attr "predicable_short_it" "no")
663 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load1,store1,fmov,mov_reg")
664 (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*")
665 (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
670 (define_insn "*movdf_vfp"
671 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r, m,w,r")
672 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,G,UvF,w ,mF,r,w,r"))]
673 "TARGET_ARM && TARGET_HARD_FLOAT
674 && ( register_operand (operands[0], DFmode)
675 || register_operand (operands[1], DFmode))"
678 switch (which_alternative)
681 return \"vmov%?\\t%P0, %Q1, %R1\";
683 return \"vmov%?\\t%Q0, %R0, %P1\";
685 gcc_assert (TARGET_VFP_DOUBLE);
686 return \"vmov%?.f64\\t%P0, %1\";
688 gcc_assert (TARGET_VFP_DOUBLE);
689 return \"vmov.i64\\t%P0, #0\\t%@ float\";
691 return output_move_vfp (operands);
693 return output_move_double (operands, true, NULL);
695 if (TARGET_VFP_SINGLE)
696 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
698 return \"vmov%?.f64\\t%P0, %P1\";
706 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,f_stored,\
707 load2,store2,ffarithd,multiple")
708 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
709 (eq_attr "alternative" "8")
711 (match_test "TARGET_VFP_SINGLE")
715 (set_attr "predicable" "yes,yes,yes,no,yes,yes,yes,yes,yes,yes")
716 (set_attr "pool_range" "*,*,*,*,1020,*,1020,*,*,*")
717 (set_attr "neg_pool_range" "*,*,*,*,1004,*,1004,*,*,*")
718 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
721 (define_insn "*thumb2_movdf_vfp"
722 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r ,m,w,r")
723 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,G,UvF,w, mF,r, w,r"))]
724 "TARGET_THUMB2 && TARGET_HARD_FLOAT
725 && ( register_operand (operands[0], DFmode)
726 || register_operand (operands[1], DFmode))"
729 switch (which_alternative)
732 return \"vmov%?\\t%P0, %Q1, %R1\";
734 return \"vmov%?\\t%Q0, %R0, %P1\";
736 gcc_assert (TARGET_VFP_DOUBLE);
737 return \"vmov%?.f64\\t%P0, %1\";
739 gcc_assert (TARGET_VFP_DOUBLE);
740 return \"vmov.i64\\t%P0, #0\\t%@ float\";
742 return output_move_vfp (operands);
743 case 6: case 7: case 9:
744 return output_move_double (operands, true, NULL);
746 if (TARGET_VFP_SINGLE)
747 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
749 return \"vmov%?.f64\\t%P0, %P1\";
755 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,\
756 f_stored,load2,store2,ffarithd,multiple")
757 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
758 (eq_attr "alternative" "8")
760 (match_test "TARGET_VFP_SINGLE")
764 (set_attr "pool_range" "*,*,*,*,1018,*,4094,*,*,*")
765 (set_attr "neg_pool_range" "*,*,*,*,1008,*,0,*,*,*")
766 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
770 ;; Conditional move patterns
772 (define_insn "*movsfcc_vfp"
773 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
775 (match_operator 3 "arm_comparison_operator"
776 [(match_operand 4 "cc_register" "") (const_int 0)])
777 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
778 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
779 "TARGET_ARM && TARGET_HARD_FLOAT"
783 vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
786 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
789 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
790 [(set_attr "conds" "use")
791 (set_attr "length" "4,4,8,4,4,8,4,4,8")
792 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
795 (define_insn "*thumb2_movsfcc_vfp"
796 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
798 (match_operator 3 "arm_comparison_operator"
799 [(match_operand 4 "cc_register" "") (const_int 0)])
800 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
801 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
802 "TARGET_THUMB2 && TARGET_HARD_FLOAT && !arm_restrict_it"
804 it\\t%D3\;vmov%D3.f32\\t%0, %2
805 it\\t%d3\;vmov%d3.f32\\t%0, %1
806 ite\\t%D3\;vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
807 it\\t%D3\;vmov%D3\\t%0, %2
808 it\\t%d3\;vmov%d3\\t%0, %1
809 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
810 it\\t%D3\;vmov%D3\\t%0, %2
811 it\\t%d3\;vmov%d3\\t%0, %1
812 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
813 [(set_attr "conds" "use")
814 (set_attr "length" "6,6,10,6,6,10,6,6,10")
815 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
818 (define_insn "*movdfcc_vfp"
819 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
821 (match_operator 3 "arm_comparison_operator"
822 [(match_operand 4 "cc_register" "") (const_int 0)])
823 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
824 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
825 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
827 vmov%D3.f64\\t%P0, %P2
828 vmov%d3.f64\\t%P0, %P1
829 vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
830 vmov%D3\\t%P0, %Q2, %R2
831 vmov%d3\\t%P0, %Q1, %R1
832 vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
833 vmov%D3\\t%Q0, %R0, %P2
834 vmov%d3\\t%Q0, %R0, %P1
835 vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
836 [(set_attr "conds" "use")
837 (set_attr "length" "4,4,8,4,4,8,4,4,8")
838 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcr,f_mrrc,f_mrrc,f_mrrc")]
841 (define_insn "*thumb2_movdfcc_vfp"
842 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
844 (match_operator 3 "arm_comparison_operator"
845 [(match_operand 4 "cc_register" "") (const_int 0)])
846 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
847 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
848 "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && !arm_restrict_it"
850 it\\t%D3\;vmov%D3.f64\\t%P0, %P2
851 it\\t%d3\;vmov%d3.f64\\t%P0, %P1
852 ite\\t%D3\;vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
853 it\t%D3\;vmov%D3\\t%P0, %Q2, %R2
854 it\t%d3\;vmov%d3\\t%P0, %Q1, %R1
855 ite\\t%D3\;vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
856 it\t%D3\;vmov%D3\\t%Q0, %R0, %P2
857 it\t%d3\;vmov%d3\\t%Q0, %R0, %P1
858 ite\\t%D3\;vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
859 [(set_attr "conds" "use")
860 (set_attr "length" "6,6,10,6,6,10,6,6,10")
861 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcrr,f_mrrc,f_mrrc,f_mrrc")]
865 ;; Sign manipulation functions
867 (define_insn "*abssf2_vfp"
868 [(set (match_operand:SF 0 "s_register_operand" "=t")
869 (abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
870 "TARGET_32BIT && TARGET_HARD_FLOAT"
871 "vabs%?.f32\\t%0, %1"
872 [(set_attr "predicable" "yes")
873 (set_attr "predicable_short_it" "no")
874 (set_attr "type" "ffariths")]
877 (define_insn "*absdf2_vfp"
878 [(set (match_operand:DF 0 "s_register_operand" "=w")
879 (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
880 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
881 "vabs%?.f64\\t%P0, %P1"
882 [(set_attr "predicable" "yes")
883 (set_attr "predicable_short_it" "no")
884 (set_attr "type" "ffarithd")]
887 (define_insn "*negsf2_vfp"
888 [(set (match_operand:SF 0 "s_register_operand" "=t,?r")
889 (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))]
890 "TARGET_32BIT && TARGET_HARD_FLOAT"
893 eor%?\\t%0, %1, #-2147483648"
894 [(set_attr "predicable" "yes")
895 (set_attr "predicable_short_it" "no")
896 (set_attr "type" "ffariths")]
899 (define_insn_and_split "*negdf2_vfp"
900 [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r")
901 (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
902 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
904 vneg%?.f64\\t%P0, %P1
907 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
908 && arm_general_register_operand (operands[0], DFmode)"
909 [(set (match_dup 0) (match_dup 1))]
911 if (REGNO (operands[0]) == REGNO (operands[1]))
913 operands[0] = gen_highpart (SImode, operands[0]);
914 operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
918 rtx in_hi, in_lo, out_hi, out_lo;
920 in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
921 GEN_INT (0x80000000));
922 in_lo = gen_lowpart (SImode, operands[1]);
923 out_hi = gen_highpart (SImode, operands[0]);
924 out_lo = gen_lowpart (SImode, operands[0]);
926 if (REGNO (in_lo) == REGNO (out_hi))
928 emit_insn (gen_rtx_SET (out_lo, in_lo));
929 operands[0] = out_hi;
934 emit_insn (gen_rtx_SET (out_hi, in_hi));
935 operands[0] = out_lo;
940 [(set_attr "predicable" "yes")
941 (set_attr "predicable_short_it" "no")
942 (set_attr "length" "4,4,8")
943 (set_attr "type" "ffarithd")]
946 ;; ABS and NEG for FP16.
947 (define_insn "<absneg_str>hf2"
948 [(set (match_operand:HF 0 "s_register_operand" "=w")
949 (ABSNEG:HF (match_operand:HF 1 "s_register_operand" "w")))]
950 "TARGET_VFP_FP16INST"
951 "v<absneg_str>.f16\t%0, %1"
952 [(set_attr "conds" "unconditional")
953 (set_attr "type" "ffariths")]
956 (define_expand "neon_vabshf"
958 (match_operand:HF 0 "s_register_operand")
959 (abs:HF (match_operand:HF 1 "s_register_operand")))]
960 "TARGET_VFP_FP16INST"
962 emit_insn (gen_abshf2 (operands[0], operands[1]));
967 (define_insn "neon_v<fp16_rnd_str>hf"
968 [(set (match_operand:HF 0 "s_register_operand" "=w")
970 [(match_operand:HF 1 "s_register_operand" "w")]
972 "TARGET_VFP_FP16INST"
973 "<fp16_rnd_insn>.f16\t%0, %1"
974 [(set_attr "conds" "unconditional")
975 (set_attr "type" "neon_fp_round_s")]
978 (define_insn "neon_vrndihf"
979 [(set (match_operand:HF 0 "s_register_operand" "=w")
981 [(match_operand:HF 1 "s_register_operand" "w")]
983 "TARGET_VFP_FP16INST"
985 [(set_attr "conds" "unconditional")
986 (set_attr "type" "neon_fp_round_s")]
991 (define_insn "addhf3"
993 (match_operand:HF 0 "s_register_operand" "=w")
995 (match_operand:HF 1 "s_register_operand" "w")
996 (match_operand:HF 2 "s_register_operand" "w")))]
997 "TARGET_VFP_FP16INST"
998 "vadd.f16\t%0, %1, %2"
999 [(set_attr "conds" "unconditional")
1000 (set_attr "type" "fadds")]
1003 (define_insn "*addsf3_vfp"
1004 [(set (match_operand:SF 0 "s_register_operand" "=t")
1005 (plus:SF (match_operand:SF 1 "s_register_operand" "t")
1006 (match_operand:SF 2 "s_register_operand" "t")))]
1007 "TARGET_32BIT && TARGET_HARD_FLOAT"
1008 "vadd%?.f32\\t%0, %1, %2"
1009 [(set_attr "predicable" "yes")
1010 (set_attr "predicable_short_it" "no")
1011 (set_attr "type" "fadds")]
1014 (define_insn "*adddf3_vfp"
1015 [(set (match_operand:DF 0 "s_register_operand" "=w")
1016 (plus:DF (match_operand:DF 1 "s_register_operand" "w")
1017 (match_operand:DF 2 "s_register_operand" "w")))]
1018 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1019 "vadd%?.f64\\t%P0, %P1, %P2"
1020 [(set_attr "predicable" "yes")
1021 (set_attr "predicable_short_it" "no")
1022 (set_attr "type" "faddd")]
1025 (define_insn "subhf3"
1027 (match_operand:HF 0 "s_register_operand" "=w")
1029 (match_operand:HF 1 "s_register_operand" "w")
1030 (match_operand:HF 2 "s_register_operand" "w")))]
1031 "TARGET_VFP_FP16INST"
1032 "vsub.f16\t%0, %1, %2"
1033 [(set_attr "conds" "unconditional")
1034 (set_attr "type" "fadds")]
1037 (define_insn "*subsf3_vfp"
1038 [(set (match_operand:SF 0 "s_register_operand" "=t")
1039 (minus:SF (match_operand:SF 1 "s_register_operand" "t")
1040 (match_operand:SF 2 "s_register_operand" "t")))]
1041 "TARGET_32BIT && TARGET_HARD_FLOAT"
1042 "vsub%?.f32\\t%0, %1, %2"
1043 [(set_attr "predicable" "yes")
1044 (set_attr "predicable_short_it" "no")
1045 (set_attr "type" "fadds")]
1048 (define_insn "*subdf3_vfp"
1049 [(set (match_operand:DF 0 "s_register_operand" "=w")
1050 (minus:DF (match_operand:DF 1 "s_register_operand" "w")
1051 (match_operand:DF 2 "s_register_operand" "w")))]
1052 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1053 "vsub%?.f64\\t%P0, %P1, %P2"
1054 [(set_attr "predicable" "yes")
1055 (set_attr "predicable_short_it" "no")
1056 (set_attr "type" "faddd")]
1063 (define_insn "divhf3"
1065 (match_operand:HF 0 "s_register_operand" "=w")
1067 (match_operand:HF 1 "s_register_operand" "w")
1068 (match_operand:HF 2 "s_register_operand" "w")))]
1069 "TARGET_VFP_FP16INST"
1070 "vdiv.f16\t%0, %1, %2"
1071 [(set_attr "conds" "unconditional")
1072 (set_attr "type" "fdivs")]
1075 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1076 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1078 (define_insn "*divsf3_vfp"
1079 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1080 (div:SF (match_operand:SF 1 "s_register_operand" "t,t")
1081 (match_operand:SF 2 "s_register_operand" "t,t")))]
1082 "TARGET_32BIT && TARGET_HARD_FLOAT"
1083 "vdiv%?.f32\\t%0, %1, %2"
1084 [(set_attr "predicable" "yes")
1085 (set_attr "predicable_short_it" "no")
1086 (set_attr "arch" "*,armv6_or_vfpv3")
1087 (set_attr "type" "fdivs")]
1090 (define_insn "*divdf3_vfp"
1091 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1092 (div:DF (match_operand:DF 1 "s_register_operand" "w,w")
1093 (match_operand:DF 2 "s_register_operand" "w,w")))]
1094 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1095 "vdiv%?.f64\\t%P0, %P1, %P2"
1096 [(set_attr "predicable" "yes")
1097 (set_attr "predicable_short_it" "no")
1098 (set_attr "arch" "*,armv6_or_vfpv3")
1099 (set_attr "type" "fdivd")]
1103 ;; Multiplication insns
1105 (define_insn "mulhf3"
1107 (match_operand:HF 0 "s_register_operand" "=w")
1108 (mult:HF (match_operand:HF 1 "s_register_operand" "w")
1109 (match_operand:HF 2 "s_register_operand" "w")))]
1110 "TARGET_VFP_FP16INST"
1111 "vmul.f16\t%0, %1, %2"
1112 [(set_attr "conds" "unconditional")
1113 (set_attr "type" "fmuls")]
1116 (define_insn "*mulsf3_vfp"
1117 [(set (match_operand:SF 0 "s_register_operand" "=t")
1118 (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1119 (match_operand:SF 2 "s_register_operand" "t")))]
1120 "TARGET_32BIT && TARGET_HARD_FLOAT"
1121 "vmul%?.f32\\t%0, %1, %2"
1122 [(set_attr "predicable" "yes")
1123 (set_attr "predicable_short_it" "no")
1124 (set_attr "type" "fmuls")]
1127 (define_insn "*muldf3_vfp"
1128 [(set (match_operand:DF 0 "s_register_operand" "=w")
1129 (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1130 (match_operand:DF 2 "s_register_operand" "w")))]
1131 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1132 "vmul%?.f64\\t%P0, %P1, %P2"
1133 [(set_attr "predicable" "yes")
1134 (set_attr "predicable_short_it" "no")
1135 (set_attr "type" "fmuld")]
1138 (define_insn "*mulsf3neghf_vfp"
1139 [(set (match_operand:HF 0 "s_register_operand" "=t")
1140 (mult:HF (neg:HF (match_operand:HF 1 "s_register_operand" "t"))
1141 (match_operand:HF 2 "s_register_operand" "t")))]
1142 "TARGET_VFP_FP16INST && !flag_rounding_math"
1143 "vnmul.f16\\t%0, %1, %2"
1144 [(set_attr "conds" "unconditional")
1145 (set_attr "type" "fmuls")]
1148 (define_insn "*negmulhf3_vfp"
1149 [(set (match_operand:HF 0 "s_register_operand" "=t")
1150 (neg:HF (mult:HF (match_operand:HF 1 "s_register_operand" "t")
1151 (match_operand:HF 2 "s_register_operand" "t"))))]
1152 "TARGET_VFP_FP16INST"
1153 "vnmul.f16\\t%0, %1, %2"
1154 [(set_attr "conds" "unconditional")
1155 (set_attr "type" "fmuls")]
1158 (define_insn "*mulsf3negsf_vfp"
1159 [(set (match_operand:SF 0 "s_register_operand" "=t")
1160 (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
1161 (match_operand:SF 2 "s_register_operand" "t")))]
1162 "TARGET_32BIT && TARGET_HARD_FLOAT && !flag_rounding_math"
1163 "vnmul%?.f32\\t%0, %1, %2"
1164 [(set_attr "predicable" "yes")
1165 (set_attr "predicable_short_it" "no")
1166 (set_attr "type" "fmuls")]
1169 (define_insn "*negmulsf3_vfp"
1170 [(set (match_operand:SF 0 "s_register_operand" "=t")
1171 (neg:SF (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1172 (match_operand:SF 2 "s_register_operand" "t"))))]
1173 "TARGET_32BIT && TARGET_HARD_FLOAT"
1174 "vnmul%?.f32\\t%0, %1, %2"
1175 [(set_attr "predicable" "yes")
1176 (set_attr "predicable_short_it" "no")
1177 (set_attr "type" "fmuls")]
1180 (define_insn "*muldf3negdf_vfp"
1181 [(set (match_operand:DF 0 "s_register_operand" "=w")
1182 (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
1183 (match_operand:DF 2 "s_register_operand" "w")))]
1184 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
1185 && !flag_rounding_math"
1186 "vnmul%?.f64\\t%P0, %P1, %P2"
1187 [(set_attr "predicable" "yes")
1188 (set_attr "predicable_short_it" "no")
1189 (set_attr "type" "fmuld")]
1192 (define_insn "*negmuldf3_vfp"
1193 [(set (match_operand:DF 0 "s_register_operand" "=w")
1194 (neg:DF (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1195 (match_operand:DF 2 "s_register_operand" "w"))))]
1196 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1197 "vnmul%?.f64\\t%P0, %P1, %P2"
1198 [(set_attr "predicable" "yes")
1199 (set_attr "predicable_short_it" "no")
1200 (set_attr "type" "fmuld")]
1204 ;; Multiply-accumulate insns
1207 (define_insn "*mulsf3addhf_vfp"
1208 [(set (match_operand:HF 0 "s_register_operand" "=t")
1210 (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1211 (match_operand:HF 3 "s_register_operand" "t"))
1212 (match_operand:HF 1 "s_register_operand" "0")))]
1213 "TARGET_VFP_FP16INST"
1214 "vmla.f16\\t%0, %2, %3"
1215 [(set_attr "conds" "unconditional")
1216 (set_attr "type" "fmacs")]
1219 (define_insn "*mulsf3addsf_vfp"
1220 [(set (match_operand:SF 0 "s_register_operand" "=t")
1221 (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1222 (match_operand:SF 3 "s_register_operand" "t"))
1223 (match_operand:SF 1 "s_register_operand" "0")))]
1224 "TARGET_32BIT && TARGET_HARD_FLOAT"
1225 "vmla%?.f32\\t%0, %2, %3"
1226 [(set_attr "predicable" "yes")
1227 (set_attr "predicable_short_it" "no")
1228 (set_attr "type" "fmacs")]
1231 (define_insn "*muldf3adddf_vfp"
1232 [(set (match_operand:DF 0 "s_register_operand" "=w")
1233 (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1234 (match_operand:DF 3 "s_register_operand" "w"))
1235 (match_operand:DF 1 "s_register_operand" "0")))]
1236 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1237 "vmla%?.f64\\t%P0, %P2, %P3"
1238 [(set_attr "predicable" "yes")
1239 (set_attr "predicable_short_it" "no")
1240 (set_attr "type" "fmacd")]
1244 (define_insn "*mulhf3subhf_vfp"
1245 [(set (match_operand:HF 0 "s_register_operand" "=t")
1246 (minus:HF (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1247 (match_operand:HF 3 "s_register_operand" "t"))
1248 (match_operand:HF 1 "s_register_operand" "0")))]
1249 "TARGET_VFP_FP16INST"
1250 "vnmls.f16\\t%0, %2, %3"
1251 [(set_attr "conds" "unconditional")
1252 (set_attr "type" "fmacs")]
1255 (define_insn "*mulsf3subsf_vfp"
1256 [(set (match_operand:SF 0 "s_register_operand" "=t")
1257 (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1258 (match_operand:SF 3 "s_register_operand" "t"))
1259 (match_operand:SF 1 "s_register_operand" "0")))]
1260 "TARGET_32BIT && TARGET_HARD_FLOAT"
1261 "vnmls%?.f32\\t%0, %2, %3"
1262 [(set_attr "predicable" "yes")
1263 (set_attr "predicable_short_it" "no")
1264 (set_attr "type" "fmacs")]
1267 (define_insn "*muldf3subdf_vfp"
1268 [(set (match_operand:DF 0 "s_register_operand" "=w")
1269 (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1270 (match_operand:DF 3 "s_register_operand" "w"))
1271 (match_operand:DF 1 "s_register_operand" "0")))]
1272 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1273 "vnmls%?.f64\\t%P0, %P2, %P3"
1274 [(set_attr "predicable" "yes")
1275 (set_attr "predicable_short_it" "no")
1276 (set_attr "type" "fmacd")]
1280 (define_insn "*mulhf3neghfaddhf_vfp"
1281 [(set (match_operand:HF 0 "s_register_operand" "=t")
1282 (minus:HF (match_operand:HF 1 "s_register_operand" "0")
1283 (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1284 (match_operand:HF 3 "s_register_operand" "t"))))]
1285 "TARGET_VFP_FP16INST"
1286 "vmls.f16\\t%0, %2, %3"
1287 [(set_attr "conds" "unconditional")
1288 (set_attr "type" "fmacs")]
1291 (define_insn "*mulsf3negsfaddsf_vfp"
1292 [(set (match_operand:SF 0 "s_register_operand" "=t")
1293 (minus:SF (match_operand:SF 1 "s_register_operand" "0")
1294 (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1295 (match_operand:SF 3 "s_register_operand" "t"))))]
1296 "TARGET_32BIT && TARGET_HARD_FLOAT"
1297 "vmls%?.f32\\t%0, %2, %3"
1298 [(set_attr "predicable" "yes")
1299 (set_attr "predicable_short_it" "no")
1300 (set_attr "type" "fmacs")]
1303 (define_insn "*fmuldf3negdfadddf_vfp"
1304 [(set (match_operand:DF 0 "s_register_operand" "=w")
1305 (minus:DF (match_operand:DF 1 "s_register_operand" "0")
1306 (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1307 (match_operand:DF 3 "s_register_operand" "w"))))]
1308 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1309 "vmls%?.f64\\t%P0, %P2, %P3"
1310 [(set_attr "predicable" "yes")
1311 (set_attr "predicable_short_it" "no")
1312 (set_attr "type" "fmacd")]
1317 (define_insn "*mulhf3neghfsubhf_vfp"
1318 [(set (match_operand:HF 0 "s_register_operand" "=t")
1320 (neg:HF (match_operand:HF 2 "s_register_operand" "t"))
1321 (match_operand:HF 3 "s_register_operand" "t"))
1322 (match_operand:HF 1 "s_register_operand" "0")))]
1323 "TARGET_VFP_FP16INST"
1324 "vnmla.f16\\t%0, %2, %3"
1325 [(set_attr "conds" "unconditional")
1326 (set_attr "type" "fmacs")]
1329 (define_insn "*mulsf3negsfsubsf_vfp"
1330 [(set (match_operand:SF 0 "s_register_operand" "=t")
1332 (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
1333 (match_operand:SF 3 "s_register_operand" "t"))
1334 (match_operand:SF 1 "s_register_operand" "0")))]
1335 "TARGET_32BIT && TARGET_HARD_FLOAT"
1336 "vnmla%?.f32\\t%0, %2, %3"
1337 [(set_attr "predicable" "yes")
1338 (set_attr "predicable_short_it" "no")
1339 (set_attr "type" "fmacs")]
1342 (define_insn "*muldf3negdfsubdf_vfp"
1343 [(set (match_operand:DF 0 "s_register_operand" "=w")
1345 (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
1346 (match_operand:DF 3 "s_register_operand" "w"))
1347 (match_operand:DF 1 "s_register_operand" "0")))]
1348 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1349 "vnmla%?.f64\\t%P0, %P2, %P3"
1350 [(set_attr "predicable" "yes")
1351 (set_attr "predicable_short_it" "no")
1352 (set_attr "type" "fmacd")]
1355 ;; Fused-multiply-accumulate
1357 (define_insn "fmahf4"
1358 [(set (match_operand:HF 0 "register_operand" "=w")
1360 (match_operand:HF 1 "register_operand" "w")
1361 (match_operand:HF 2 "register_operand" "w")
1362 (match_operand:HF 3 "register_operand" "0")))]
1363 "TARGET_VFP_FP16INST"
1364 "vfma.f16\\t%0, %1, %2"
1365 [(set_attr "conds" "unconditional")
1366 (set_attr "type" "ffmas")]
1369 (define_expand "neon_vfmahf"
1370 [(match_operand:HF 0 "s_register_operand")
1371 (match_operand:HF 1 "s_register_operand")
1372 (match_operand:HF 2 "s_register_operand")
1373 (match_operand:HF 3 "s_register_operand")]
1374 "TARGET_VFP_FP16INST"
1376 emit_insn (gen_fmahf4 (operands[0], operands[2], operands[3],
1381 (define_insn "fma<SDF:mode>4"
1382 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1383 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1384 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1385 (match_operand:SDF 3 "register_operand" "0")))]
1386 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1387 "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1388 [(set_attr "predicable" "yes")
1389 (set_attr "predicable_short_it" "no")
1390 (set_attr "type" "ffma<vfp_type>")]
1393 (define_insn "fmsubhf4_fp16"
1394 [(set (match_operand:HF 0 "register_operand" "=w")
1396 (neg:HF (match_operand:HF 1 "register_operand" "w"))
1397 (match_operand:HF 2 "register_operand" "w")
1398 (match_operand:HF 3 "register_operand" "0")))]
1399 "TARGET_VFP_FP16INST"
1400 "vfms.f16\\t%0, %1, %2"
1401 [(set_attr "conds" "unconditional")
1402 (set_attr "type" "ffmas")]
1405 (define_expand "neon_vfmshf"
1406 [(match_operand:HF 0 "s_register_operand")
1407 (match_operand:HF 1 "s_register_operand")
1408 (match_operand:HF 2 "s_register_operand")
1409 (match_operand:HF 3 "s_register_operand")]
1410 "TARGET_VFP_FP16INST"
1412 emit_insn (gen_fmsubhf4_fp16 (operands[0], operands[2], operands[3],
1417 (define_insn "*fmsub<SDF:mode>4"
1418 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1419 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1421 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1422 (match_operand:SDF 3 "register_operand" "0")))]
1423 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1424 "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1425 [(set_attr "predicable" "yes")
1426 (set_attr "predicable_short_it" "no")
1427 (set_attr "type" "ffma<vfp_type>")]
1430 (define_insn "*fnmsubhf4"
1431 [(set (match_operand:HF 0 "register_operand" "=w")
1432 (fma:HF (match_operand:HF 1 "register_operand" "w")
1433 (match_operand:HF 2 "register_operand" "w")
1434 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1435 "TARGET_VFP_FP16INST"
1436 "vfnms.f16\\t%0, %1, %2"
1437 [(set_attr "conds" "unconditional")
1438 (set_attr "type" "ffmas")]
1441 (define_insn "*fnmsub<SDF:mode>4"
1442 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1443 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1444 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1445 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1446 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1447 "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1448 [(set_attr "predicable" "yes")
1449 (set_attr "predicable_short_it" "no")
1450 (set_attr "type" "ffma<vfp_type>")]
1453 (define_insn "*fnmaddhf4"
1454 [(set (match_operand:HF 0 "register_operand" "=w")
1455 (fma:HF (neg:HF (match_operand:HF 1 "register_operand" "w"))
1456 (match_operand:HF 2 "register_operand" "w")
1457 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1458 "TARGET_VFP_FP16INST"
1459 "vfnma.f16\\t%0, %1, %2"
1460 [(set_attr "conds" "unconditional")
1461 (set_attr "type" "ffmas")]
1464 (define_insn "*fnmadd<SDF:mode>4"
1465 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1466 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1468 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1469 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1470 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1471 "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1472 [(set_attr "predicable" "yes")
1473 (set_attr "predicable_short_it" "no")
1474 (set_attr "type" "ffma<vfp_type>")]
1478 ;; Conversion routines
1480 (define_insn "*extendsfdf2_vfp"
1481 [(set (match_operand:DF 0 "s_register_operand" "=w")
1482 (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
1483 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1484 "vcvt%?.f64.f32\\t%P0, %1"
1485 [(set_attr "predicable" "yes")
1486 (set_attr "predicable_short_it" "no")
1487 (set_attr "type" "f_cvt")]
1490 (define_insn "*truncdfsf2_vfp"
1491 [(set (match_operand:SF 0 "s_register_operand" "=t")
1492 (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
1493 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1494 "vcvt%?.f32.f64\\t%0, %P1"
1495 [(set_attr "predicable" "yes")
1496 (set_attr "predicable_short_it" "no")
1497 (set_attr "type" "f_cvt")]
1500 (define_insn "extendhfsf2"
1501 [(set (match_operand:SF 0 "s_register_operand" "=t")
1502 (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))]
1503 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1504 "vcvtb%?.f32.f16\\t%0, %1"
1505 [(set_attr "predicable" "yes")
1506 (set_attr "predicable_short_it" "no")
1507 (set_attr "type" "f_cvt")]
1510 (define_insn "*truncdfhf2"
1511 [(set (match_operand:HF 0 "s_register_operand" "=t")
1512 (float_truncate:HF (match_operand:DF 1 "s_register_operand" "w")))]
1513 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1514 "vcvtb%?.f16.f64\\t%0, %P1"
1515 [(set_attr "predicable" "yes")
1516 (set_attr "predicable_short_it" "no")
1517 (set_attr "type" "f_cvt")]
1520 (define_insn "*extendhfdf2"
1521 [(set (match_operand:DF 0 "s_register_operand" "=w")
1522 (float_extend:DF (match_operand:HF 1 "s_register_operand" "t")))]
1523 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1524 "vcvtb%?.f64.f16\\t%P0, %1"
1525 [(set_attr "predicable" "yes")
1526 (set_attr "predicable_short_it" "no")
1527 (set_attr "type" "f_cvt")]
1530 (define_insn "truncsfhf2"
1531 [(set (match_operand:HF 0 "s_register_operand" "=t")
1532 (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
1533 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1534 "vcvtb%?.f16.f32\\t%0, %1"
1535 [(set_attr "predicable" "yes")
1536 (set_attr "predicable_short_it" "no")
1537 (set_attr "type" "f_cvt")]
1540 (define_insn "*truncsisf2_vfp"
1541 [(set (match_operand:SI 0 "s_register_operand" "=t")
1542 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1543 "TARGET_32BIT && TARGET_HARD_FLOAT"
1544 "vcvt%?.s32.f32\\t%0, %1"
1545 [(set_attr "predicable" "yes")
1546 (set_attr "predicable_short_it" "no")
1547 (set_attr "type" "f_cvtf2i")]
1550 (define_insn "*truncsidf2_vfp"
1551 [(set (match_operand:SI 0 "s_register_operand" "=t")
1552 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
1553 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1554 "vcvt%?.s32.f64\\t%0, %P1"
1555 [(set_attr "predicable" "yes")
1556 (set_attr "predicable_short_it" "no")
1557 (set_attr "type" "f_cvtf2i")]
1561 (define_insn "fixuns_truncsfsi2"
1562 [(set (match_operand:SI 0 "s_register_operand" "=t")
1563 (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1564 "TARGET_32BIT && TARGET_HARD_FLOAT"
1565 "vcvt%?.u32.f32\\t%0, %1"
1566 [(set_attr "predicable" "yes")
1567 (set_attr "predicable_short_it" "no")
1568 (set_attr "type" "f_cvtf2i")]
1571 (define_insn "fixuns_truncdfsi2"
1572 [(set (match_operand:SI 0 "s_register_operand" "=t")
1573 (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
1574 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1575 "vcvt%?.u32.f64\\t%0, %P1"
1576 [(set_attr "predicable" "yes")
1577 (set_attr "predicable_short_it" "no")
1578 (set_attr "type" "f_cvtf2i")]
1582 (define_insn "*floatsisf2_vfp"
1583 [(set (match_operand:SF 0 "s_register_operand" "=t")
1584 (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1585 "TARGET_32BIT && TARGET_HARD_FLOAT"
1586 "vcvt%?.f32.s32\\t%0, %1"
1587 [(set_attr "predicable" "yes")
1588 (set_attr "predicable_short_it" "no")
1589 (set_attr "type" "f_cvti2f")]
1592 (define_insn "*floatsidf2_vfp"
1593 [(set (match_operand:DF 0 "s_register_operand" "=w")
1594 (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1595 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1596 "vcvt%?.f64.s32\\t%P0, %1"
1597 [(set_attr "predicable" "yes")
1598 (set_attr "predicable_short_it" "no")
1599 (set_attr "type" "f_cvti2f")]
1603 (define_insn "floatunssisf2"
1604 [(set (match_operand:SF 0 "s_register_operand" "=t")
1605 (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1606 "TARGET_32BIT && TARGET_HARD_FLOAT"
1607 "vcvt%?.f32.u32\\t%0, %1"
1608 [(set_attr "predicable" "yes")
1609 (set_attr "predicable_short_it" "no")
1610 (set_attr "type" "f_cvti2f")]
1613 (define_insn "floatunssidf2"
1614 [(set (match_operand:DF 0 "s_register_operand" "=w")
1615 (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1616 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1617 "vcvt%?.f64.u32\\t%P0, %1"
1618 [(set_attr "predicable" "yes")
1619 (set_attr "predicable_short_it" "no")
1620 (set_attr "type" "f_cvti2f")]
1626 (define_insn "neon_vsqrthf"
1627 [(set (match_operand:HF 0 "s_register_operand" "=w")
1628 (sqrt:HF (match_operand:HF 1 "s_register_operand" "w")))]
1629 "TARGET_VFP_FP16INST"
1631 [(set_attr "conds" "unconditional")
1632 (set_attr "type" "fsqrts")]
1635 (define_insn "neon_vrsqrtshf"
1637 (match_operand:HF 0 "s_register_operand" "=w")
1638 (unspec:HF [(match_operand:HF 1 "s_register_operand" "w")
1639 (match_operand:HF 2 "s_register_operand" "w")]
1641 "TARGET_VFP_FP16INST"
1642 "vrsqrts.f16\t%0, %1, %2"
1643 [(set_attr "conds" "unconditional")
1644 (set_attr "type" "fsqrts")]
1647 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1648 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1650 (define_insn "*sqrtsf2_vfp"
1651 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1652 (sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))]
1653 "TARGET_32BIT && TARGET_HARD_FLOAT"
1654 "vsqrt%?.f32\\t%0, %1"
1655 [(set_attr "predicable" "yes")
1656 (set_attr "predicable_short_it" "no")
1657 (set_attr "arch" "*,armv6_or_vfpv3")
1658 (set_attr "type" "fsqrts")]
1661 (define_insn "*sqrtdf2_vfp"
1662 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1663 (sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))]
1664 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1665 "vsqrt%?.f64\\t%P0, %P1"
1666 [(set_attr "predicable" "yes")
1667 (set_attr "predicable_short_it" "no")
1668 (set_attr "arch" "*,armv6_or_vfpv3")
1669 (set_attr "type" "fsqrtd")]
1673 ;; Patterns to split/copy vfp condition flags.
1675 (define_insn "*movcc_vfp"
1676 [(set (reg CC_REGNUM)
1677 (reg VFPCC_REGNUM))]
1678 "TARGET_32BIT && TARGET_HARD_FLOAT"
1679 "vmrs%?\\tAPSR_nzcv, FPSCR"
1680 [(set_attr "conds" "set")
1681 (set_attr "type" "f_flag")]
1684 (define_insn_and_split "*cmpsf_split_vfp"
1685 [(set (reg:CCFP CC_REGNUM)
1686 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t")
1687 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1688 "TARGET_32BIT && TARGET_HARD_FLOAT"
1690 "TARGET_32BIT && TARGET_HARD_FLOAT"
1691 [(set (reg:CCFP VFPCC_REGNUM)
1692 (compare:CCFP (match_dup 0)
1694 (set (reg:CCFP CC_REGNUM)
1695 (reg:CCFP VFPCC_REGNUM))]
1699 (define_insn_and_split "*cmpsf_trap_split_vfp"
1700 [(set (reg:CCFPE CC_REGNUM)
1701 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t")
1702 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1703 "TARGET_32BIT && TARGET_HARD_FLOAT"
1705 "TARGET_32BIT && TARGET_HARD_FLOAT"
1706 [(set (reg:CCFPE VFPCC_REGNUM)
1707 (compare:CCFPE (match_dup 0)
1709 (set (reg:CCFPE CC_REGNUM)
1710 (reg:CCFPE VFPCC_REGNUM))]
1714 (define_insn_and_split "*cmpdf_split_vfp"
1715 [(set (reg:CCFP CC_REGNUM)
1716 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
1717 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1718 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1720 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1721 [(set (reg:CCFP VFPCC_REGNUM)
1722 (compare:CCFP (match_dup 0)
1724 (set (reg:CCFP CC_REGNUM)
1725 (reg:CCFP VFPCC_REGNUM))]
1729 (define_insn_and_split "*cmpdf_trap_split_vfp"
1730 [(set (reg:CCFPE CC_REGNUM)
1731 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
1732 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1733 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1735 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1736 [(set (reg:CCFPE VFPCC_REGNUM)
1737 (compare:CCFPE (match_dup 0)
1739 (set (reg:CCFPE CC_REGNUM)
1740 (reg:CCFPE VFPCC_REGNUM))]
1745 ;; Comparison patterns
1747 ;; In the compare with FP zero case the ARM Architecture Reference Manual
1748 ;; specifies the immediate to be #0.0. However, some buggy assemblers only
1749 ;; accept #0. We don't want to autodetect broken assemblers, so output #0.
1750 (define_insn "*cmpsf_vfp"
1751 [(set (reg:CCFP VFPCC_REGNUM)
1752 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t,t")
1753 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1754 "TARGET_32BIT && TARGET_HARD_FLOAT"
1757 vcmp%?.f32\\t%0, #0"
1758 [(set_attr "predicable" "yes")
1759 (set_attr "predicable_short_it" "no")
1760 (set_attr "type" "fcmps")]
1763 (define_insn "*cmpsf_trap_vfp"
1764 [(set (reg:CCFPE VFPCC_REGNUM)
1765 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t,t")
1766 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1767 "TARGET_32BIT && TARGET_HARD_FLOAT"
1769 vcmpe%?.f32\\t%0, %1
1770 vcmpe%?.f32\\t%0, #0"
1771 [(set_attr "predicable" "yes")
1772 (set_attr "predicable_short_it" "no")
1773 (set_attr "type" "fcmps")]
1776 (define_insn "*cmpdf_vfp"
1777 [(set (reg:CCFP VFPCC_REGNUM)
1778 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
1779 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1780 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1782 vcmp%?.f64\\t%P0, %P1
1783 vcmp%?.f64\\t%P0, #0"
1784 [(set_attr "predicable" "yes")
1785 (set_attr "predicable_short_it" "no")
1786 (set_attr "type" "fcmpd")]
1789 (define_insn "*cmpdf_trap_vfp"
1790 [(set (reg:CCFPE VFPCC_REGNUM)
1791 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
1792 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1793 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1795 vcmpe%?.f64\\t%P0, %P1
1796 vcmpe%?.f64\\t%P0, #0"
1797 [(set_attr "predicable" "yes")
1798 (set_attr "predicable_short_it" "no")
1799 (set_attr "type" "fcmpd")]
1802 ;; Fixed point to floating point conversions.
1803 (define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1804 [(set (match_operand:SF 0 "s_register_operand" "=t")
1805 (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
1807 "const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1808 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1809 "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2"
1810 [(set_attr "predicable" "yes")
1811 (set_attr "predicable_short_it" "no")
1812 (set_attr "type" "f_cvti2f")]
1815 ;; Not the ideal way of implementing this. Ideally we would be able to split
1816 ;; this into a move to a DP register and then a vcvt.f64.i32
1817 (define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1818 [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1819 (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
1821 "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
1822 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
1823 && !TARGET_VFP_SINGLE"
1825 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1826 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1827 vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1828 [(set_attr "predicable" "yes")
1829 (set_attr "ce_count" "2")
1830 (set_attr "predicable_short_it" "no")
1831 (set_attr "type" "f_cvti2f")
1832 (set_attr "length" "8")]
1835 (define_insn "*combine_vcvtf2i"
1836 [(set (match_operand:SI 0 "s_register_operand" "=t")
1837 (fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0")
1839 "const_double_vcvt_power_of_two" "Dp")))))]
1840 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1841 "vcvt%?.s32.f32\\t%0, %1, %v2"
1842 [(set_attr "predicable" "yes")
1843 (set_attr "predicable_short_it" "no")
1844 (set_attr "type" "f_cvtf2i")]
1847 ;; FP16 conversions.
1848 (define_insn "neon_vcvth<sup>hf"
1849 [(set (match_operand:HF 0 "s_register_operand" "=w")
1851 [(match_operand:SI 1 "s_register_operand" "w")]
1853 "TARGET_VFP_FP16INST"
1854 "vcvt.f16.<sup>%#32\t%0, %1"
1855 [(set_attr "conds" "unconditional")
1856 (set_attr "type" "f_cvti2f")]
1859 (define_insn "neon_vcvth<sup>si"
1860 [(set (match_operand:SI 0 "s_register_operand" "=w")
1862 [(match_operand:HF 1 "s_register_operand" "w")]
1864 "TARGET_VFP_FP16INST"
1865 "vcvt.<sup>%#32.f16\t%0, %1"
1866 [(set_attr "conds" "unconditional")
1867 (set_attr "type" "f_cvtf2i")]
1870 ;; The neon_vcvth<sup>_nhf patterns are used to generate the instruction for the
1871 ;; vcvth_n_f16_<sup>32 arm_fp16 intrinsics. They are complicated by the
1872 ;; hardware requirement that the source and destination registers are the same
1873 ;; despite having different machine modes. The approach is to use a temporary
1874 ;; register for the conversion and move that to the correct destination.
1876 ;; Generate an unspec pattern for the intrinsic.
1877 (define_insn "neon_vcvth<sup>_nhf_unspec"
1879 (match_operand:SI 0 "s_register_operand" "=w")
1881 [(match_operand:SI 1 "s_register_operand" "0")
1882 (match_operand:SI 2 "immediate_operand" "i")]
1885 (match_operand:HF 3 "s_register_operand" "=w")
1886 (float_truncate:HF (float:SF (match_dup 0))))]
1887 "TARGET_VFP_FP16INST"
1889 arm_const_bounds (operands[2], 1, 33);
1890 return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1892 [(set_attr "conds" "unconditional")
1893 (set_attr "type" "f_cvti2f")]
1896 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1897 (define_expand "neon_vcvth<sup>_nhf"
1898 [(match_operand:HF 0 "s_register_operand")
1899 (unspec:HF [(match_operand:SI 1 "s_register_operand")
1900 (match_operand:SI 2 "immediate_operand")]
1902 "TARGET_VFP_FP16INST"
1904 rtx op1 = gen_reg_rtx (SImode);
1906 arm_const_bounds (operands[2], 1, 33);
1908 emit_move_insn (op1, operands[1]);
1909 emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2],
1914 ;; The neon_vcvth<sup>_nsi patterns are used to generate the instruction for the
1915 ;; vcvth_n_<sup>32_f16 arm_fp16 intrinsics. They have the same restrictions and
1916 ;; are implemented in the same way as the neon_vcvth<sup>_nhf patterns.
1918 ;; Generate an unspec pattern, constraining the registers.
1919 (define_insn "neon_vcvth<sup>_nsi_unspec"
1920 [(set (match_operand:SI 0 "s_register_operand" "=w")
1925 (match_operand:HF 1 "s_register_operand" "w"))))
1926 (match_operand:SI 2 "immediate_operand" "i")]
1928 "TARGET_VFP_FP16INST"
1930 arm_const_bounds (operands[2], 1, 33);
1931 return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1933 [(set_attr "conds" "unconditional")
1934 (set_attr "type" "f_cvtf2i")]
1937 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1938 (define_expand "neon_vcvth<sup>_nsi"
1939 [(match_operand:SI 0 "s_register_operand")
1941 [(match_operand:HF 1 "s_register_operand")
1942 (match_operand:SI 2 "immediate_operand")]
1944 "TARGET_VFP_FP16INST"
1946 rtx op1 = gen_reg_rtx (SImode);
1948 arm_const_bounds (operands[2], 1, 33);
1949 emit_insn (gen_neon_vcvth<sup>_nsi_unspec (op1, operands[1], operands[2]));
1950 emit_move_insn (operands[0], op1);
1954 (define_insn "neon_vcvt<vcvth_op>h<sup>si"
1956 (match_operand:SI 0 "s_register_operand" "=w")
1958 [(match_operand:HF 1 "s_register_operand" "w")]
1960 "TARGET_VFP_FP16INST"
1961 "vcvt<vcvth_op>.<sup>%#32.f16\t%0, %1"
1962 [(set_attr "conds" "unconditional")
1963 (set_attr "type" "f_cvtf2i")]
1966 ;; Store multiple insn used in function prologue.
1967 (define_insn "*push_multi_vfp"
1968 [(match_parallel 2 "multi_register_push"
1969 [(set (match_operand:BLK 0 "memory_operand" "=m")
1970 (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
1971 UNSPEC_PUSH_MULT))])]
1972 "TARGET_32BIT && TARGET_HARD_FLOAT"
1973 "* return vfp_output_vstmd (operands);"
1974 [(set_attr "type" "f_stored")]
1977 ;; VRINT round to integral instructions.
1978 ;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
1979 ;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
1980 ;; rintsf2, rintdf2.
1981 (define_insn "<vrint_pattern><SDF:mode>2"
1982 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1983 (unspec:SDF [(match_operand:SDF 1
1984 "register_operand" "<F_constraint>")]
1986 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1987 "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
1988 [(set_attr "predicable" "<vrint_predicable>")
1989 (set_attr "predicable_short_it" "no")
1990 (set_attr "type" "f_rint<vfp_type>")
1991 (set_attr "conds" "<vrint_conds>")]
1994 ;; Implements the lround, lfloor and lceil optabs.
1995 (define_insn "l<vrint_pattern><su_optab><mode>si2"
1996 [(set (match_operand:SI 0 "register_operand" "=t")
1997 (FIXUORS:SI (unspec:SDF
1998 [(match_operand:SDF 1
1999 "register_operand" "<F_constraint>")] VCVT)))]
2000 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
2001 "vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1"
2002 [(set_attr "predicable" "no")
2003 (set_attr "conds" "unconditional")
2004 (set_attr "type" "f_cvtf2i")]
2007 ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
2008 ;; The 'smax' and 'smin' RTL standard pattern names do not specify which
2009 ;; operand will be returned when both operands are zero (i.e. they may not
2010 ;; honour signed zeroes), or when either operand is NaN. Therefore GCC
2011 ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
2014 (define_insn "smax<mode>3"
2015 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
2016 (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
2017 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
2018 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2019 "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2020 [(set_attr "type" "f_minmax<vfp_type>")
2021 (set_attr "conds" "unconditional")]
2024 (define_insn "smin<mode>3"
2025 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
2026 (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
2027 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
2028 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2029 "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2030 [(set_attr "type" "f_minmax<vfp_type>")
2031 (set_attr "conds" "unconditional")]
2034 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
2036 (define_insn "neon_<fmaxmin_op>hf"
2038 (match_operand:HF 0 "s_register_operand" "=w")
2040 [(match_operand:HF 1 "s_register_operand" "w")
2041 (match_operand:HF 2 "s_register_operand" "w")]
2043 "TARGET_VFP_FP16INST"
2044 "<fmaxmin_op>.f16\t%0, %1, %2"
2045 [(set_attr "conds" "unconditional")
2046 (set_attr "type" "f_minmaxs")]
2049 (define_insn "<fmaxmin><mode>3"
2050 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
2051 (unspec:SDF [(match_operand:SDF 1 "s_register_operand" "<F_constraint>")
2052 (match_operand:SDF 2 "s_register_operand" "<F_constraint>")]
2054 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2055 "<fmaxmin_op>.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2056 [(set_attr "type" "f_minmax<vfp_type>")
2057 (set_attr "conds" "unconditional")]
2060 ;; Write Floating-point Status and Control Register.
2061 (define_insn "set_fpscr"
2062 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)]
2064 "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
2065 [(set_attr "type" "mrs")])
2067 ;; Read Floating-point Status and Control Register.
2068 (define_insn "get_fpscr"
2069 [(set (match_operand:SI 0 "register_operand" "=r")
2070 (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
2072 "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
2073 [(set_attr "type" "mrs")])
2076 ;; Unimplemented insns:
2079 ;; fmdhr et al (VFPv1)
2080 ;; Support for xD (single precision only) variants.