1 ;; ARM VFP instruction patterns
2 ;; Copyright (C) 2003-2013 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/>. */
22 ;; ??? For now do not allow loading constants into vfp regs. This causes
23 ;; problems because small constants get converted into adds.
24 (define_insn "*arm_movsi_vfp"
25 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv")
26 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk,r,*t,*t,*Uvi,*t"))]
27 "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
28 && ( s_register_operand (operands[0], SImode)
29 || s_register_operand (operands[1], SImode))"
31 switch (which_alternative)
34 return \"mov%?\\t%0, %1\";
36 return \"mvn%?\\t%0, #%B1\";
38 return \"movw%?\\t%0, %1\";
40 return \"ldr%?\\t%0, %1\";
42 return \"str%?\\t%1, %0\";
44 return \"fmsr%?\\t%0, %1\\t%@ int\";
46 return \"fmrs%?\\t%0, %1\\t%@ int\";
48 return \"fcpys%?\\t%0, %1\\t%@ int\";
50 return output_move_vfp (operands);
55 [(set_attr "predicable" "yes")
56 (set_attr "type" "mov_reg,mov_reg,mvn_imm,mov_imm,load1,store1,r_2_f,f_2_r,fcpys,f_loads,f_stores")
57 (set_attr "neon_type" "*,*,*,*,*,*,neon_mcr,neon_mrc,neon_vmov,*,*")
58 (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*")
59 (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")]
62 ;; See thumb2.md:thumb2_movsi_insn for an explanation of the split
63 ;; high/low register alternatives for loads and stores here.
64 ;; The l/Py alternative should come after r/I to ensure that the short variant
65 ;; is chosen with length 2 when the instruction is predicated for
67 (define_insn "*thumb2_movsi_vfp"
68 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r, l,*hk,m, *m,*t, r,*t,*t, *Uv")
69 (match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,*mi,l,*hk, r,*t,*t,*Uvi,*t"))]
70 "TARGET_THUMB2 && TARGET_VFP && TARGET_HARD_FLOAT
71 && ( s_register_operand (operands[0], SImode)
72 || s_register_operand (operands[1], SImode))"
74 switch (which_alternative)
79 return \"mov%?\\t%0, %1\";
81 return \"mvn%?\\t%0, #%B1\";
83 return \"movw%?\\t%0, %1\";
86 return \"ldr%?\\t%0, %1\";
89 return \"str%?\\t%1, %0\";
91 return \"fmsr%?\\t%0, %1\\t%@ int\";
93 return \"fmrs%?\\t%0, %1\\t%@ int\";
95 return \"fcpys%?\\t%0, %1\\t%@ int\";
97 return output_move_vfp (operands);
102 [(set_attr "predicable" "yes")
103 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no")
104 (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_reg,load1,load1,store1,store1,r_2_f,f_2_r,fcpys,f_loads,f_stores")
105 (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4")
106 (set_attr "neon_type" "*,*,*,*,*,*,*,*,*,neon_mcr,neon_mrc,neon_vmov,*,*")
107 (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*")
108 (set_attr "neg_pool_range" "*,*,*,*,*, 0, 0,*,*,*,*,*,1008,*")]
114 (define_insn "*movdi_vfp"
115 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,q,q,m,w,r,w,w, Uv")
116 (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,q,r,w,w,Uvi,w"))]
117 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune != cortexa8
118 && ( register_operand (operands[0], DImode)
119 || register_operand (operands[1], DImode))
120 && !(TARGET_NEON && CONST_INT_P (operands[1])
121 && neon_immediate_valid_for_move (operands[1], DImode, NULL, NULL))"
123 switch (which_alternative)
133 return output_move_double (operands, true, NULL);
135 return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
137 return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\";
139 if (TARGET_VFP_SINGLE)
140 return \"fcpys%?\\t%0, %1\\t%@ int\;fcpys%?\\t%p0, %p1\\t%@ int\";
142 return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
144 return output_move_vfp (operands);
149 [(set_attr "type" "*,*,*,*,load2,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored")
150 (set_attr "neon_type" "*,*,*,*,*,*,*,neon_mcr_2_mcrr,neon_mrrc,neon_vmov,*,*")
151 (set (attr "length") (cond [(eq_attr "alternative" "1,4,5,6") (const_int 8)
152 (eq_attr "alternative" "2") (const_int 12)
153 (eq_attr "alternative" "3") (const_int 16)
154 (eq_attr "alternative" "9")
156 (match_test "TARGET_VFP_SINGLE")
160 (set_attr "arm_pool_range" "*,*,*,*,1020,4096,*,*,*,*,1020,*")
161 (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
162 (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
163 (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
166 (define_insn "*movdi_vfp_cortexa8"
167 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,r,r,m,w,!r,w,w, Uv")
168 (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,r,r,w,w,Uvi,w"))]
169 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune == cortexa8
170 && ( register_operand (operands[0], DImode)
171 || register_operand (operands[1], DImode))
172 && !(TARGET_NEON && CONST_INT_P (operands[1])
173 && neon_immediate_valid_for_move (operands[1], DImode, NULL, NULL))"
175 switch (which_alternative)
185 return output_move_double (operands, true, NULL);
187 return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
189 return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\";
191 return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
193 return output_move_vfp (operands);
198 [(set_attr "type" "*,*,*,*,load2,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored")
199 (set_attr "neon_type" "*,*,*,*,*,*,*,neon_mcr_2_mcrr,neon_mrrc,neon_vmov,*,*")
200 (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8)
201 (eq_attr "alternative" "2") (const_int 12)
202 (eq_attr "alternative" "3") (const_int 16)
203 (eq_attr "alternative" "4,5,6")
205 "arm_count_output_move_double_insns (operands) \
208 (set_attr "predicable" "yes")
209 (set_attr "arm_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
210 (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
211 (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
212 (set (attr "ce_count")
213 (symbol_ref "get_attr_length (insn) / 4"))
214 (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
218 (define_insn "*movhf_vfp_neon"
219 [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r")
220 (match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))]
221 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_NEON_FP16
222 && ( s_register_operand (operands[0], HFmode)
223 || s_register_operand (operands[1], HFmode))"
225 switch (which_alternative)
227 case 0: /* S register from memory */
228 return \"vld1.16\\t{%z0}, %A1\";
229 case 1: /* memory from S register */
230 return \"vst1.16\\t{%z1}, %A0\";
231 case 2: /* ARM register from memory */
232 return \"ldrh\\t%0, %1\\t%@ __fp16\";
233 case 3: /* memory from ARM register */
234 return \"strh\\t%1, %0\\t%@ __fp16\";
235 case 4: /* S register from S register */
236 return \"fcpys\\t%0, %1\";
237 case 5: /* ARM register from ARM register */
238 return \"mov\\t%0, %1\\t%@ __fp16\";
239 case 6: /* S register from ARM register */
240 return \"fmsr\\t%0, %1\";
241 case 7: /* ARM register from S register */
242 return \"fmrs\\t%0, %1\";
243 case 8: /* ARM register from constant */
249 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
250 bits = real_to_target (NULL, &r, HFmode);
251 ops[0] = operands[0];
252 ops[1] = GEN_INT (bits);
253 ops[2] = GEN_INT (bits & 0xff00);
254 ops[3] = GEN_INT (bits & 0x00ff);
257 output_asm_insn (\"movw\\t%0, %1\", ops);
259 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
266 [(set_attr "conds" "unconditional")
267 (set_attr "type" "*,*,load1,store1,fcpys,*,r_2_f,f_2_r,*")
268 (set_attr "neon_type" "neon_vld1_1_2_regs,neon_vst1_1_2_regs_vst2_2_regs,*,*,*,*,*,*,*")
269 (set_attr "length" "4,4,4,4,4,4,4,4,8")]
272 ;; FP16 without element load/store instructions.
273 (define_insn "*movhf_vfp"
274 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
275 (match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))]
276 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16 && !TARGET_NEON_FP16
277 && ( s_register_operand (operands[0], HFmode)
278 || s_register_operand (operands[1], HFmode))"
280 switch (which_alternative)
282 case 0: /* ARM register from memory */
283 return \"ldrh\\t%0, %1\\t%@ __fp16\";
284 case 1: /* memory from ARM register */
285 return \"strh\\t%1, %0\\t%@ __fp16\";
286 case 2: /* S register from S register */
287 return \"fcpys\\t%0, %1\";
288 case 3: /* ARM register from ARM register */
289 return \"mov\\t%0, %1\\t%@ __fp16\";
290 case 4: /* S register from ARM register */
291 return \"fmsr\\t%0, %1\";
292 case 5: /* ARM register from S register */
293 return \"fmrs\\t%0, %1\";
294 case 6: /* ARM register from constant */
300 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
301 bits = real_to_target (NULL, &r, HFmode);
302 ops[0] = operands[0];
303 ops[1] = GEN_INT (bits);
304 ops[2] = GEN_INT (bits & 0xff00);
305 ops[3] = GEN_INT (bits & 0x00ff);
308 output_asm_insn (\"movw\\t%0, %1\", ops);
310 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
317 [(set_attr "conds" "unconditional")
318 (set_attr "type" "load1,store1,fcpys,*,r_2_f,f_2_r,*")
319 (set_attr "length" "4,4,4,4,4,4,8")]
324 ;; Disparage the w<->r cases because reloading an invalid address is
325 ;; preferable to loading the value via integer registers.
327 (define_insn "*movsf_vfp"
328 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t ,Uv,r ,m,t,r")
329 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
330 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
331 && ( s_register_operand (operands[0], SFmode)
332 || s_register_operand (operands[1], SFmode))"
334 switch (which_alternative)
337 return \"fmsr%?\\t%0, %1\";
339 return \"fmrs%?\\t%0, %1\";
341 return \"fconsts%?\\t%0, #%G1\";
343 return output_move_vfp (operands);
345 return \"ldr%?\\t%0, %1\\t%@ float\";
347 return \"str%?\\t%1, %0\\t%@ float\";
349 return \"fcpys%?\\t%0, %1\";
351 return \"mov%?\\t%0, %1\\t%@ float\";
356 [(set_attr "predicable" "yes")
358 "r_2_f,f_2_r,fconsts,f_loads,f_stores,load1,store1,fcpys,mov_reg")
359 (set_attr "neon_type" "neon_mcr,neon_mrc,*,*,*,*,*,neon_vmov,*")
360 (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
361 (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
364 (define_insn "*thumb2_movsf_vfp"
365 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t ,Uv,r ,m,t,r")
366 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
367 "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP
368 && ( s_register_operand (operands[0], SFmode)
369 || s_register_operand (operands[1], SFmode))"
371 switch (which_alternative)
374 return \"fmsr%?\\t%0, %1\";
376 return \"fmrs%?\\t%0, %1\";
378 return \"fconsts%?\\t%0, #%G1\";
380 return output_move_vfp (operands);
382 return \"ldr%?\\t%0, %1\\t%@ float\";
384 return \"str%?\\t%1, %0\\t%@ float\";
386 return \"fcpys%?\\t%0, %1\";
388 return \"mov%?\\t%0, %1\\t%@ float\";
393 [(set_attr "predicable" "yes")
394 (set_attr "predicable_short_it" "no")
396 "r_2_f,f_2_r,fconsts,f_loads,f_stores,load1,store1,fcpys,mov_reg")
397 (set_attr "neon_type" "neon_mcr,neon_mrc,*,*,*,*,*,neon_vmov,*")
398 (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*")
399 (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
404 (define_insn "*movdf_vfp"
405 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w ,Uv,r, m,w,r")
406 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,UvF,w ,mF,r,w,r"))]
407 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
408 && ( register_operand (operands[0], DFmode)
409 || register_operand (operands[1], DFmode))"
412 switch (which_alternative)
415 return \"fmdrr%?\\t%P0, %Q1, %R1\";
417 return \"fmrrd%?\\t%Q0, %R0, %P1\";
419 gcc_assert (TARGET_VFP_DOUBLE);
420 return \"fconstd%?\\t%P0, #%G1\";
422 return output_move_vfp (operands);
424 return output_move_double (operands, true, NULL);
426 if (TARGET_VFP_SINGLE)
427 return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
429 return \"fcpyd%?\\t%P0, %P1\";
438 "r_2_f,f_2_r,fconstd,f_loadd,f_stored,load2,store2,ffarithd,*")
439 (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,*,*,*,*,neon_vmov,*")
440 (set (attr "length") (cond [(eq_attr "alternative" "5,6,8") (const_int 8)
441 (eq_attr "alternative" "7")
443 (match_test "TARGET_VFP_SINGLE")
447 (set_attr "predicable" "yes")
448 (set_attr "pool_range" "*,*,*,1020,*,1020,*,*,*")
449 (set_attr "neg_pool_range" "*,*,*,1004,*,1004,*,*,*")]
452 (define_insn "*thumb2_movdf_vfp"
453 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w ,Uv,r ,m,w,r")
454 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,UvF,w, mF,r, w,r"))]
455 "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP
456 && ( register_operand (operands[0], DFmode)
457 || register_operand (operands[1], DFmode))"
460 switch (which_alternative)
463 return \"fmdrr%?\\t%P0, %Q1, %R1\";
465 return \"fmrrd%?\\t%Q0, %R0, %P1\";
467 gcc_assert (TARGET_VFP_DOUBLE);
468 return \"fconstd%?\\t%P0, #%G1\";
470 return output_move_vfp (operands);
471 case 5: case 6: case 8:
472 return output_move_double (operands, true, NULL);
474 if (TARGET_VFP_SINGLE)
475 return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
477 return \"fcpyd%?\\t%P0, %P1\";
484 "r_2_f,f_2_r,fconstd,f_loadd,f_stored,load2,store2,ffarithd,*")
485 (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,*,*,*,*,neon_vmov,*")
486 (set (attr "length") (cond [(eq_attr "alternative" "5,6,8") (const_int 8)
487 (eq_attr "alternative" "7")
489 (match_test "TARGET_VFP_SINGLE")
493 (set_attr "pool_range" "*,*,*,1018,*,4094,*,*,*")
494 (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
498 ;; Conditional move patterns
500 (define_insn "*movsfcc_vfp"
501 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
503 (match_operator 3 "arm_comparison_operator"
504 [(match_operand 4 "cc_register" "") (const_int 0)])
505 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
506 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
507 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
511 fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
514 fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
517 fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
518 [(set_attr "conds" "use")
519 (set_attr "length" "4,4,8,4,4,8,4,4,8")
520 (set_attr "type" "fcpys,fcpys,fcpys,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")
521 (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr,neon_mcr,neon_mcr,neon_mrc,neon_mrc,neon_mrc")]
524 (define_insn "*thumb2_movsfcc_vfp"
525 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
527 (match_operator 3 "arm_comparison_operator"
528 [(match_operand 4 "cc_register" "") (const_int 0)])
529 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
530 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
531 "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP && !arm_restrict_it"
533 it\\t%D3\;fcpys%D3\\t%0, %2
534 it\\t%d3\;fcpys%d3\\t%0, %1
535 ite\\t%D3\;fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
536 it\\t%D3\;fmsr%D3\\t%0, %2
537 it\\t%d3\;fmsr%d3\\t%0, %1
538 ite\\t%D3\;fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
539 it\\t%D3\;fmrs%D3\\t%0, %2
540 it\\t%d3\;fmrs%d3\\t%0, %1
541 ite\\t%D3\;fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
542 [(set_attr "conds" "use")
543 (set_attr "length" "6,6,10,6,6,10,6,6,10")
544 (set_attr "type" "fcpys,fcpys,fcpys,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")
545 (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr,neon_mcr,neon_mcr,neon_mrc,neon_mrc,neon_mrc")]
548 (define_insn "*movdfcc_vfp"
549 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
551 (match_operator 3 "arm_comparison_operator"
552 [(match_operand 4 "cc_register" "") (const_int 0)])
553 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
554 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
555 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
559 fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
560 fmdrr%D3\\t%P0, %Q2, %R2
561 fmdrr%d3\\t%P0, %Q1, %R1
562 fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
563 fmrrd%D3\\t%Q0, %R0, %P2
564 fmrrd%d3\\t%Q0, %R0, %P1
565 fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
566 [(set_attr "conds" "use")
567 (set_attr "length" "4,4,8,4,4,8,4,4,8")
568 (set_attr "type" "ffarithd,ffarithd,ffarithd,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")
569 (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mrrc,neon_mrrc,neon_mrrc")]
572 (define_insn "*thumb2_movdfcc_vfp"
573 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
575 (match_operator 3 "arm_comparison_operator"
576 [(match_operand 4 "cc_register" "") (const_int 0)])
577 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
578 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
579 "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && !arm_restrict_it"
581 it\\t%D3\;fcpyd%D3\\t%P0, %P2
582 it\\t%d3\;fcpyd%d3\\t%P0, %P1
583 ite\\t%D3\;fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
584 it\t%D3\;fmdrr%D3\\t%P0, %Q2, %R2
585 it\t%d3\;fmdrr%d3\\t%P0, %Q1, %R1
586 ite\\t%D3\;fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
587 it\t%D3\;fmrrd%D3\\t%Q0, %R0, %P2
588 it\t%d3\;fmrrd%d3\\t%Q0, %R0, %P1
589 ite\\t%D3\;fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
590 [(set_attr "conds" "use")
591 (set_attr "length" "6,6,10,6,6,10,6,6,10")
592 (set_attr "type" "ffarithd,ffarithd,ffarithd,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")
593 (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mrrc,neon_mrrc,neon_mrrc")]
597 ;; Sign manipulation functions
599 (define_insn "*abssf2_vfp"
600 [(set (match_operand:SF 0 "s_register_operand" "=t")
601 (abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
602 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604 [(set_attr "predicable" "yes")
605 (set_attr "predicable_short_it" "no")
606 (set_attr "type" "ffariths")]
609 (define_insn "*absdf2_vfp"
610 [(set (match_operand:DF 0 "s_register_operand" "=w")
611 (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
612 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
614 [(set_attr "predicable" "yes")
615 (set_attr "predicable_short_it" "no")
616 (set_attr "type" "ffarithd")]
619 (define_insn "*negsf2_vfp"
620 [(set (match_operand:SF 0 "s_register_operand" "=t,?r")
621 (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))]
622 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
625 eor%?\\t%0, %1, #-2147483648"
626 [(set_attr "predicable" "yes")
627 (set_attr "predicable_short_it" "no")
628 (set_attr "type" "ffariths")]
631 (define_insn_and_split "*negdf2_vfp"
632 [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r")
633 (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
634 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
639 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
640 && arm_general_register_operand (operands[0], DFmode)"
641 [(set (match_dup 0) (match_dup 1))]
643 if (REGNO (operands[0]) == REGNO (operands[1]))
645 operands[0] = gen_highpart (SImode, operands[0]);
646 operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
650 rtx in_hi, in_lo, out_hi, out_lo;
652 in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
653 GEN_INT (0x80000000));
654 in_lo = gen_lowpart (SImode, operands[1]);
655 out_hi = gen_highpart (SImode, operands[0]);
656 out_lo = gen_lowpart (SImode, operands[0]);
658 if (REGNO (in_lo) == REGNO (out_hi))
660 emit_insn (gen_rtx_SET (SImode, out_lo, in_lo));
661 operands[0] = out_hi;
666 emit_insn (gen_rtx_SET (SImode, out_hi, in_hi));
667 operands[0] = out_lo;
672 [(set_attr "predicable" "yes")
673 (set_attr "predicable_short_it" "no")
674 (set_attr "length" "4,4,8")
675 (set_attr "type" "ffarithd")]
681 (define_insn "*addsf3_vfp"
682 [(set (match_operand:SF 0 "s_register_operand" "=t")
683 (plus:SF (match_operand:SF 1 "s_register_operand" "t")
684 (match_operand:SF 2 "s_register_operand" "t")))]
685 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
686 "fadds%?\\t%0, %1, %2"
687 [(set_attr "predicable" "yes")
688 (set_attr "predicable_short_it" "no")
689 (set_attr "type" "fadds")]
692 (define_insn "*adddf3_vfp"
693 [(set (match_operand:DF 0 "s_register_operand" "=w")
694 (plus:DF (match_operand:DF 1 "s_register_operand" "w")
695 (match_operand:DF 2 "s_register_operand" "w")))]
696 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
697 "faddd%?\\t%P0, %P1, %P2"
698 [(set_attr "predicable" "yes")
699 (set_attr "predicable_short_it" "no")
700 (set_attr "type" "faddd")]
704 (define_insn "*subsf3_vfp"
705 [(set (match_operand:SF 0 "s_register_operand" "=t")
706 (minus:SF (match_operand:SF 1 "s_register_operand" "t")
707 (match_operand:SF 2 "s_register_operand" "t")))]
708 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
709 "fsubs%?\\t%0, %1, %2"
710 [(set_attr "predicable" "yes")
711 (set_attr "predicable_short_it" "no")
712 (set_attr "type" "fadds")]
715 (define_insn "*subdf3_vfp"
716 [(set (match_operand:DF 0 "s_register_operand" "=w")
717 (minus:DF (match_operand:DF 1 "s_register_operand" "w")
718 (match_operand:DF 2 "s_register_operand" "w")))]
719 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
720 "fsubd%?\\t%P0, %P1, %P2"
721 [(set_attr "predicable" "yes")
722 (set_attr "predicable_short_it" "no")
723 (set_attr "type" "faddd")]
729 (define_insn "*divsf3_vfp"
730 [(set (match_operand:SF 0 "s_register_operand" "=t")
731 (div:SF (match_operand:SF 1 "s_register_operand" "t")
732 (match_operand:SF 2 "s_register_operand" "t")))]
733 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
734 "fdivs%?\\t%0, %1, %2"
735 [(set_attr "predicable" "yes")
736 (set_attr "predicable_short_it" "no")
737 (set_attr "type" "fdivs")]
740 (define_insn "*divdf3_vfp"
741 [(set (match_operand:DF 0 "s_register_operand" "=w")
742 (div:DF (match_operand:DF 1 "s_register_operand" "w")
743 (match_operand:DF 2 "s_register_operand" "w")))]
744 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
745 "fdivd%?\\t%P0, %P1, %P2"
746 [(set_attr "predicable" "yes")
747 (set_attr "predicable_short_it" "no")
748 (set_attr "type" "fdivd")]
752 ;; Multiplication insns
754 (define_insn "*mulsf3_vfp"
755 [(set (match_operand:SF 0 "s_register_operand" "=t")
756 (mult:SF (match_operand:SF 1 "s_register_operand" "t")
757 (match_operand:SF 2 "s_register_operand" "t")))]
758 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
759 "fmuls%?\\t%0, %1, %2"
760 [(set_attr "predicable" "yes")
761 (set_attr "predicable_short_it" "no")
762 (set_attr "type" "fmuls")]
765 (define_insn "*muldf3_vfp"
766 [(set (match_operand:DF 0 "s_register_operand" "=w")
767 (mult:DF (match_operand:DF 1 "s_register_operand" "w")
768 (match_operand:DF 2 "s_register_operand" "w")))]
769 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
770 "fmuld%?\\t%P0, %P1, %P2"
771 [(set_attr "predicable" "yes")
772 (set_attr "predicable_short_it" "no")
773 (set_attr "type" "fmuld")]
776 (define_insn "*mulsf3negsf_vfp"
777 [(set (match_operand:SF 0 "s_register_operand" "=t")
778 (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
779 (match_operand:SF 2 "s_register_operand" "t")))]
780 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
781 "fnmuls%?\\t%0, %1, %2"
782 [(set_attr "predicable" "yes")
783 (set_attr "predicable_short_it" "no")
784 (set_attr "type" "fmuls")]
787 (define_insn "*muldf3negdf_vfp"
788 [(set (match_operand:DF 0 "s_register_operand" "=w")
789 (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
790 (match_operand:DF 2 "s_register_operand" "w")))]
791 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
792 "fnmuld%?\\t%P0, %P1, %P2"
793 [(set_attr "predicable" "yes")
794 (set_attr "predicable_short_it" "no")
795 (set_attr "type" "fmuld")]
799 ;; Multiply-accumulate insns
802 (define_insn "*mulsf3addsf_vfp"
803 [(set (match_operand:SF 0 "s_register_operand" "=t")
804 (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
805 (match_operand:SF 3 "s_register_operand" "t"))
806 (match_operand:SF 1 "s_register_operand" "0")))]
807 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
808 "fmacs%?\\t%0, %2, %3"
809 [(set_attr "predicable" "yes")
810 (set_attr "predicable_short_it" "no")
811 (set_attr "type" "fmacs")]
814 (define_insn "*muldf3adddf_vfp"
815 [(set (match_operand:DF 0 "s_register_operand" "=w")
816 (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
817 (match_operand:DF 3 "s_register_operand" "w"))
818 (match_operand:DF 1 "s_register_operand" "0")))]
819 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
820 "fmacd%?\\t%P0, %P2, %P3"
821 [(set_attr "predicable" "yes")
822 (set_attr "predicable_short_it" "no")
823 (set_attr "type" "fmacd")]
827 (define_insn "*mulsf3subsf_vfp"
828 [(set (match_operand:SF 0 "s_register_operand" "=t")
829 (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
830 (match_operand:SF 3 "s_register_operand" "t"))
831 (match_operand:SF 1 "s_register_operand" "0")))]
832 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
833 "fmscs%?\\t%0, %2, %3"
834 [(set_attr "predicable" "yes")
835 (set_attr "predicable_short_it" "no")
836 (set_attr "type" "fmacs")]
839 (define_insn "*muldf3subdf_vfp"
840 [(set (match_operand:DF 0 "s_register_operand" "=w")
841 (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
842 (match_operand:DF 3 "s_register_operand" "w"))
843 (match_operand:DF 1 "s_register_operand" "0")))]
844 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
845 "fmscd%?\\t%P0, %P2, %P3"
846 [(set_attr "predicable" "yes")
847 (set_attr "predicable_short_it" "no")
848 (set_attr "type" "fmacd")]
852 (define_insn "*mulsf3negsfaddsf_vfp"
853 [(set (match_operand:SF 0 "s_register_operand" "=t")
854 (minus:SF (match_operand:SF 1 "s_register_operand" "0")
855 (mult:SF (match_operand:SF 2 "s_register_operand" "t")
856 (match_operand:SF 3 "s_register_operand" "t"))))]
857 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
858 "fnmacs%?\\t%0, %2, %3"
859 [(set_attr "predicable" "yes")
860 (set_attr "predicable_short_it" "no")
861 (set_attr "type" "fmacs")]
864 (define_insn "*fmuldf3negdfadddf_vfp"
865 [(set (match_operand:DF 0 "s_register_operand" "=w")
866 (minus:DF (match_operand:DF 1 "s_register_operand" "0")
867 (mult:DF (match_operand:DF 2 "s_register_operand" "w")
868 (match_operand:DF 3 "s_register_operand" "w"))))]
869 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
870 "fnmacd%?\\t%P0, %P2, %P3"
871 [(set_attr "predicable" "yes")
872 (set_attr "predicable_short_it" "no")
873 (set_attr "type" "fmacd")]
878 (define_insn "*mulsf3negsfsubsf_vfp"
879 [(set (match_operand:SF 0 "s_register_operand" "=t")
881 (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
882 (match_operand:SF 3 "s_register_operand" "t"))
883 (match_operand:SF 1 "s_register_operand" "0")))]
884 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
885 "fnmscs%?\\t%0, %2, %3"
886 [(set_attr "predicable" "yes")
887 (set_attr "predicable_short_it" "no")
888 (set_attr "type" "fmacs")]
891 (define_insn "*muldf3negdfsubdf_vfp"
892 [(set (match_operand:DF 0 "s_register_operand" "=w")
894 (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
895 (match_operand:DF 3 "s_register_operand" "w"))
896 (match_operand:DF 1 "s_register_operand" "0")))]
897 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
898 "fnmscd%?\\t%P0, %P2, %P3"
899 [(set_attr "predicable" "yes")
900 (set_attr "predicable_short_it" "no")
901 (set_attr "type" "fmacd")]
904 ;; Fused-multiply-accumulate
906 (define_insn "fma<SDF:mode>4"
907 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
908 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
909 (match_operand:SDF 2 "register_operand" "<F_constraint>")
910 (match_operand:SDF 3 "register_operand" "0")))]
911 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
912 "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
913 [(set_attr "predicable" "yes")
914 (set_attr "predicable_short_it" "no")
915 (set_attr "type" "ffma<vfp_type>")]
918 (define_insn "*fmsub<SDF:mode>4"
919 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
920 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
922 (match_operand:SDF 2 "register_operand" "<F_constraint>")
923 (match_operand:SDF 3 "register_operand" "0")))]
924 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
925 "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
926 [(set_attr "predicable" "yes")
927 (set_attr "predicable_short_it" "no")
928 (set_attr "type" "ffma<vfp_type>")]
931 (define_insn "*fnmsub<SDF:mode>4"
932 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
933 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
934 (match_operand:SDF 2 "register_operand" "<F_constraint>")
935 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
936 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
937 "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
938 [(set_attr "predicable" "yes")
939 (set_attr "predicable_short_it" "no")
940 (set_attr "type" "ffma<vfp_type>")]
943 (define_insn "*fnmadd<SDF:mode>4"
944 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
945 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
947 (match_operand:SDF 2 "register_operand" "<F_constraint>")
948 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
949 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
950 "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
951 [(set_attr "predicable" "yes")
952 (set_attr "predicable_short_it" "no")
953 (set_attr "type" "ffma<vfp_type>")]
957 ;; Conversion routines
959 (define_insn "*extendsfdf2_vfp"
960 [(set (match_operand:DF 0 "s_register_operand" "=w")
961 (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
962 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
964 [(set_attr "predicable" "yes")
965 (set_attr "predicable_short_it" "no")
966 (set_attr "type" "f_cvt")]
969 (define_insn "*truncdfsf2_vfp"
970 [(set (match_operand:SF 0 "s_register_operand" "=t")
971 (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
972 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
974 [(set_attr "predicable" "yes")
975 (set_attr "predicable_short_it" "no")
976 (set_attr "type" "f_cvt")]
979 (define_insn "extendhfsf2"
980 [(set (match_operand:SF 0 "s_register_operand" "=t")
981 (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))]
982 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16"
983 "vcvtb%?.f32.f16\\t%0, %1"
984 [(set_attr "predicable" "yes")
985 (set_attr "predicable_short_it" "no")
986 (set_attr "type" "f_cvt")]
989 (define_insn "truncsfhf2"
990 [(set (match_operand:HF 0 "s_register_operand" "=t")
991 (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
992 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16"
993 "vcvtb%?.f16.f32\\t%0, %1"
994 [(set_attr "predicable" "yes")
995 (set_attr "predicable_short_it" "no")
996 (set_attr "type" "f_cvt")]
999 (define_insn "*truncsisf2_vfp"
1000 [(set (match_operand:SI 0 "s_register_operand" "=t")
1001 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1002 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1003 "ftosizs%?\\t%0, %1"
1004 [(set_attr "predicable" "yes")
1005 (set_attr "predicable_short_it" "no")
1006 (set_attr "type" "f_cvt")]
1009 (define_insn "*truncsidf2_vfp"
1010 [(set (match_operand:SI 0 "s_register_operand" "=t")
1011 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
1012 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1013 "ftosizd%?\\t%0, %P1"
1014 [(set_attr "predicable" "yes")
1015 (set_attr "predicable_short_it" "no")
1016 (set_attr "type" "f_cvt")]
1020 (define_insn "fixuns_truncsfsi2"
1021 [(set (match_operand:SI 0 "s_register_operand" "=t")
1022 (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1023 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1024 "ftouizs%?\\t%0, %1"
1025 [(set_attr "predicable" "yes")
1026 (set_attr "predicable_short_it" "no")
1027 (set_attr "type" "f_cvt")]
1030 (define_insn "fixuns_truncdfsi2"
1031 [(set (match_operand:SI 0 "s_register_operand" "=t")
1032 (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
1033 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1034 "ftouizd%?\\t%0, %P1"
1035 [(set_attr "predicable" "yes")
1036 (set_attr "predicable_short_it" "no")
1037 (set_attr "type" "f_cvt")]
1041 (define_insn "*floatsisf2_vfp"
1042 [(set (match_operand:SF 0 "s_register_operand" "=t")
1043 (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1044 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1046 [(set_attr "predicable" "yes")
1047 (set_attr "predicable_short_it" "no")
1048 (set_attr "type" "f_cvt")]
1051 (define_insn "*floatsidf2_vfp"
1052 [(set (match_operand:DF 0 "s_register_operand" "=w")
1053 (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1054 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1055 "fsitod%?\\t%P0, %1"
1056 [(set_attr "predicable" "yes")
1057 (set_attr "predicable_short_it" "no")
1058 (set_attr "type" "f_cvt")]
1062 (define_insn "floatunssisf2"
1063 [(set (match_operand:SF 0 "s_register_operand" "=t")
1064 (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1065 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1067 [(set_attr "predicable" "yes")
1068 (set_attr "predicable_short_it" "no")
1069 (set_attr "type" "f_cvt")]
1072 (define_insn "floatunssidf2"
1073 [(set (match_operand:DF 0 "s_register_operand" "=w")
1074 (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1075 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1076 "fuitod%?\\t%P0, %1"
1077 [(set_attr "predicable" "yes")
1078 (set_attr "predicable_short_it" "no")
1079 (set_attr "type" "f_cvt")]
1085 (define_insn "*sqrtsf2_vfp"
1086 [(set (match_operand:SF 0 "s_register_operand" "=t")
1087 (sqrt:SF (match_operand:SF 1 "s_register_operand" "t")))]
1088 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1090 [(set_attr "predicable" "yes")
1091 (set_attr "predicable_short_it" "no")
1092 (set_attr "type" "fdivs")]
1095 (define_insn "*sqrtdf2_vfp"
1096 [(set (match_operand:DF 0 "s_register_operand" "=w")
1097 (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
1098 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1099 "fsqrtd%?\\t%P0, %P1"
1100 [(set_attr "predicable" "yes")
1101 (set_attr "predicable_short_it" "no")
1102 (set_attr "type" "fdivd")]
1106 ;; Patterns to split/copy vfp condition flags.
1108 (define_insn "*movcc_vfp"
1109 [(set (reg CC_REGNUM)
1110 (reg VFPCC_REGNUM))]
1111 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1113 [(set_attr "conds" "set")
1114 (set_attr "type" "f_flag")]
1117 (define_insn_and_split "*cmpsf_split_vfp"
1118 [(set (reg:CCFP CC_REGNUM)
1119 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t")
1120 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1121 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1123 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1124 [(set (reg:CCFP VFPCC_REGNUM)
1125 (compare:CCFP (match_dup 0)
1127 (set (reg:CCFP CC_REGNUM)
1128 (reg:CCFP VFPCC_REGNUM))]
1132 (define_insn_and_split "*cmpsf_trap_split_vfp"
1133 [(set (reg:CCFPE CC_REGNUM)
1134 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t")
1135 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1136 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1138 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1139 [(set (reg:CCFPE VFPCC_REGNUM)
1140 (compare:CCFPE (match_dup 0)
1142 (set (reg:CCFPE CC_REGNUM)
1143 (reg:CCFPE VFPCC_REGNUM))]
1147 (define_insn_and_split "*cmpdf_split_vfp"
1148 [(set (reg:CCFP CC_REGNUM)
1149 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
1150 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1151 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1153 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1154 [(set (reg:CCFP VFPCC_REGNUM)
1155 (compare:CCFP (match_dup 0)
1157 (set (reg:CCFP CC_REGNUM)
1158 (reg:CCFP VFPCC_REGNUM))]
1162 (define_insn_and_split "*cmpdf_trap_split_vfp"
1163 [(set (reg:CCFPE CC_REGNUM)
1164 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
1165 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1166 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1168 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1169 [(set (reg:CCFPE VFPCC_REGNUM)
1170 (compare:CCFPE (match_dup 0)
1172 (set (reg:CCFPE CC_REGNUM)
1173 (reg:CCFPE VFPCC_REGNUM))]
1178 ;; Comparison patterns
1180 (define_insn "*cmpsf_vfp"
1181 [(set (reg:CCFP VFPCC_REGNUM)
1182 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t,t")
1183 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1184 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1188 [(set_attr "predicable" "yes")
1189 (set_attr "predicable_short_it" "no")
1190 (set_attr "type" "fcmps")]
1193 (define_insn "*cmpsf_trap_vfp"
1194 [(set (reg:CCFPE VFPCC_REGNUM)
1195 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t,t")
1196 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1197 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1201 [(set_attr "predicable" "yes")
1202 (set_attr "predicable_short_it" "no")
1203 (set_attr "type" "fcmps")]
1206 (define_insn "*cmpdf_vfp"
1207 [(set (reg:CCFP VFPCC_REGNUM)
1208 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
1209 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1210 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1214 [(set_attr "predicable" "yes")
1215 (set_attr "predicable_short_it" "no")
1216 (set_attr "type" "fcmpd")]
1219 (define_insn "*cmpdf_trap_vfp"
1220 [(set (reg:CCFPE VFPCC_REGNUM)
1221 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
1222 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1223 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1227 [(set_attr "predicable" "yes")
1228 (set_attr "predicable_short_it" "no")
1229 (set_attr "type" "fcmpd")]
1232 ;; Fixed point to floating point conversions.
1233 (define_code_iterator FCVT [unsigned_float float])
1234 (define_code_attr FCVTI32typename [(unsigned_float "u32") (float "s32")])
1236 (define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1237 [(set (match_operand:SF 0 "s_register_operand" "=t")
1238 (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
1240 "const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1241 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1242 "vcvt.f32.<FCVTI32typename>\\t%0, %1, %v2"
1243 [(set_attr "predicable" "no")
1244 (set_attr "type" "f_cvt")]
1247 ;; Not the ideal way of implementing this. Ideally we would be able to split
1248 ;; this into a move to a DP register and then a vcvt.f64.i32
1249 (define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1250 [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1251 (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
1253 "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
1254 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
1255 && !TARGET_VFP_SINGLE"
1257 vmov.f32\\t%0, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1258 vmov.f32\\t%0, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1259 vmov.f64\\t%P0, %1, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1260 [(set_attr "predicable" "no")
1261 (set_attr "type" "f_cvt")
1262 (set_attr "length" "8")]
1265 ;; Store multiple insn used in function prologue.
1266 (define_insn "*push_multi_vfp"
1267 [(match_parallel 2 "multi_register_push"
1268 [(set (match_operand:BLK 0 "memory_operand" "=m")
1269 (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
1270 UNSPEC_PUSH_MULT))])]
1271 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1272 "* return vfp_output_fstmd (operands);"
1273 [(set_attr "type" "f_stored")]
1276 ;; VRINT round to integral instructions.
1277 ;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
1278 ;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
1279 ;; rintsf2, rintdf2.
1280 (define_insn "<vrint_pattern><SDF:mode>2"
1281 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1282 (unspec:SDF [(match_operand:SDF 1
1283 "register_operand" "<F_constraint>")]
1285 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
1286 "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
1287 [(set_attr "predicable" "<vrint_predicable>")
1288 (set_attr "predicable_short_it" "no")
1289 (set_attr "type" "f_rint<vfp_type>")]
1292 ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
1293 ;; The 'smax' and 'smin' RTL standard pattern names do not specify which
1294 ;; operand will be returned when both operands are zero (i.e. they may not
1295 ;; honour signed zeroes), or when either operand is NaN. Therefore GCC
1296 ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
1299 (define_insn "smax<mode>3"
1300 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1301 (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1302 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1303 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
1304 "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1305 [(set_attr "type" "f_minmax<vfp_type>")]
1308 (define_insn "smin<mode>3"
1309 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1310 (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1311 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1312 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
1313 "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1314 [(set_attr "type" "f_minmax<vfp_type>")]
1317 ;; Unimplemented insns:
1320 ;; fmdhr et al (VFPv1)
1321 ;; Support for xD (single precision only) variants.