]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/vfp.md
[ARM] Implement support for ACLE Coprocessor CDP intrinsics
[thirdparty/gcc.git] / gcc / config / arm / vfp.md
1 ;; ARM VFP instruction patterns
2 ;; Copyright (C) 2003-2017 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11 ;;
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
16 ;;
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>. */
20
21 ;; Patterns for HI moves which provide more data transfer instructions when VFP
22 ;; support is enabled.
23 (define_insn "*arm_movhi_vfp"
24 [(set
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))"
33 {
34 switch (which_alternative)
35 {
36 case 0:
37 return "mov%?\t%0, %1\t%@ movhi";
38 case 1:
39 return "mvn%?\t%0, #%B1\t%@ movhi";
40 case 2:
41 return "movw%?\t%0, %L1\t%@ movhi";
42 case 3:
43 return "strh%?\t%1, %0\t%@ movhi";
44 case 4:
45 return "ldrh%?\t%0, %1\t%@ movhi";
46 case 5:
47 case 6:
48 return "vmov%?\t%0, %1\t%@ int";
49 case 7:
50 return "vmov%?.f32\t%0, %1\t%@ int";
51 default:
52 gcc_unreachable ();
53 }
54 }
55 [(set_attr "predicable" "yes")
56 (set_attr_alternative "type"
57 [(if_then_else
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")]
72 )
73
74 (define_insn "*thumb2_movhi_vfp"
75 [(set
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))"
84 {
85 switch (which_alternative)
86 {
87 case 0:
88 case 1:
89 case 2:
90 return "mov%?\t%0, %1\t%@ movhi";
91 case 3:
92 return "movw%?\t%0, %L1\t%@ movhi";
93 case 4:
94 return "strh%?\t%1, %0\t%@ movhi";
95 case 5:
96 return "ldrh%?\t%0, %1\t%@ movhi";
97 case 6:
98 case 7:
99 return "vmov%?\t%0, %1\t%@ int";
100 case 8:
101 return "vmov%?.f32\t%0, %1\t%@ int";
102 default:
103 gcc_unreachable ();
104 }
105 }
106 [(set_attr "predicable" "yes")
107 (set_attr "predicable_short_it"
108 "yes, no, yes, no, no, no, no, no, no")
109 (set_attr "type"
110 "mov_reg, mov_imm, mov_imm, mov_imm, store1, load1,\
111 f_mcr, f_mrc, fmov")
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")]
116 )
117
118 ;; Patterns for HI moves which provide more data transfer instructions when FP16
119 ;; instructions are available.
120 (define_insn "*arm_movhi_fp16"
121 [(set
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))"
129 {
130 switch (which_alternative)
131 {
132 case 0:
133 return "mov%?\t%0, %1\t%@ movhi";
134 case 1:
135 return "mvn%?\t%0, #%B1\t%@ movhi";
136 case 2:
137 return "movw%?\t%0, %L1\t%@ movhi";
138 case 3:
139 return "strh%?\t%1, %0\t%@ movhi";
140 case 4:
141 return "ldrh%?\t%0, %1\t%@ movhi";
142 case 5:
143 case 6:
144 return "vmov.f16\t%0, %1\t%@ int";
145 case 7:
146 return "vmov%?.f32\t%0, %1\t%@ int";
147 default:
148 gcc_unreachable ();
149 }
150 }
151 [(set_attr "predicable" "yes, yes, yes, yes, yes, no, no, yes")
152 (set_attr_alternative "type"
153 [(if_then_else
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")]
168 )
169
170 (define_insn "*thumb2_movhi_fp16"
171 [(set
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))"
179 {
180 switch (which_alternative)
181 {
182 case 0:
183 case 1:
184 case 2:
185 return "mov%?\t%0, %1\t%@ movhi";
186 case 3:
187 return "movw%?\t%0, %L1\t%@ movhi";
188 case 4:
189 return "strh%?\t%1, %0\t%@ movhi";
190 case 5:
191 return "ldrh%?\t%0, %1\t%@ movhi";
192 case 6:
193 case 7:
194 return "vmov.f16\t%0, %1\t%@ int";
195 case 8:
196 return "vmov%?.f32\t%0, %1\t%@ int";
197 default:
198 gcc_unreachable ();
199 }
200 }
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")
205 (set_attr "type"
206 "mov_reg, mov_imm, mov_imm, mov_imm, store1, load1,\
207 f_mcr, f_mrc, fmov")
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")]
212 )
213
214 ;; SImode moves
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))"
223 "*
224 switch (which_alternative)
225 {
226 case 0: case 1:
227 return \"mov%?\\t%0, %1\";
228 case 2:
229 return \"mvn%?\\t%0, #%B1\";
230 case 3:
231 return \"movw%?\\t%0, %1\";
232 case 4:
233 return \"ldr%?\\t%0, %1\";
234 case 5:
235 return \"str%?\\t%1, %0\";
236 case 6:
237 return \"vmov%?\\t%0, %1\\t%@ int\";
238 case 7:
239 return \"vmov%?\\t%0, %1\\t%@ int\";
240 case 8:
241 return \"vmov%?.f32\\t%0, %1\\t%@ int\";
242 case 9: case 10:
243 return output_move_vfp (operands);
244 default:
245 gcc_unreachable ();
246 }
247 "
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,*")]
253 )
254
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
259 ;; arm_restrict_it.
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))"
266 "*
267 switch (which_alternative)
268 {
269 case 0:
270 case 1:
271 case 2:
272 return \"mov%?\\t%0, %1\";
273 case 3:
274 return \"mvn%?\\t%0, #%B1\";
275 case 4:
276 return \"movw%?\\t%0, %1\";
277 case 5:
278 case 6:
279 return \"ldr%?\\t%0, %1\";
280 case 7:
281 case 8:
282 return \"str%?\\t%1, %0\";
283 case 9:
284 return \"vmov%?\\t%0, %1\\t%@ int\";
285 case 10:
286 return \"vmov%?\\t%0, %1\\t%@ int\";
287 case 11:
288 return \"vmov%?.f32\\t%0, %1\\t%@ int\";
289 case 12: case 13:
290 return output_move_vfp (operands);
291 default:
292 gcc_unreachable ();
293 }
294 "
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,*")]
301 )
302
303
304 ;; DImode moves
305
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))"
314 "*
315 switch (which_alternative)
316 {
317 case 0:
318 case 1:
319 case 2:
320 case 3:
321 return \"#\";
322 case 4:
323 case 5:
324 case 6:
325 return output_move_double (operands, true, NULL);
326 case 7:
327 return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\";
328 case 8:
329 return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\";
330 case 9:
331 if (TARGET_VFP_SINGLE)
332 return \"vmov%?.f32\\t%0, %1\\t%@ int\;vmov%?.f32\\t%p0, %p1\\t%@ int\";
333 else
334 return \"vmov%?.f64\\t%P0, %P1\\t%@ int\";
335 case 10: case 11:
336 return output_move_vfp (operands);
337 default:
338 gcc_unreachable ();
339 }
340 "
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")
346 (if_then_else
347 (match_test "TARGET_VFP_SINGLE")
348 (const_int 8)
349 (const_int 4))]
350 (const_int 4)))
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")]
355 )
356
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))"
365 "*
366 switch (which_alternative)
367 {
368 case 0:
369 case 1:
370 case 2:
371 case 3:
372 return \"#\";
373 case 4:
374 case 5:
375 case 6:
376 return output_move_double (operands, true, NULL);
377 case 7:
378 return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\";
379 case 8:
380 return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\";
381 case 9:
382 return \"vmov%?.f64\\t%P0, %P1\\t%@ int\";
383 case 10: case 11:
384 return output_move_vfp (operands);
385 default:
386 gcc_unreachable ();
387 }
388 "
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")
394 (symbol_ref
395 "arm_count_output_move_double_insns (operands) \
396 * 4")]
397 (const_int 4)))
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")]
405 )
406
407 ;; HFmode moves
408
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"))]
414 "TARGET_32BIT
415 && TARGET_VFP_FP16INST
416 && (s_register_operand (operands[0], HFmode)
417 || s_register_operand (operands[1], HFmode))"
418 {
419 switch (which_alternative)
420 {
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. */
438 {
439 long bits;
440 rtx ops[4];
441
442 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
443 HFmode);
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);
448
449 if (arm_arch_thumb2)
450 output_asm_insn (\"movw\\t%0, %1\", ops);
451 else
452 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
453 return \"\";
454 }
455 default:
456 gcc_unreachable ();
457 }
458 }
459 [(set_attr "predicable" "yes, yes, no, yes, no, no, no, no, no, no")
460 (set_attr "predicable_short_it" "no, no, no, yes,\
461 no, no, no, no,\
462 no, no")
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)
477 (const_int 4)
478 (if_then_else (match_test "arm_arch_thumb2")
479 (const_int 4)
480 (const_int 8))])]
481 )
482
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"))]
486 "TARGET_32BIT
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))"
491 "*
492 switch (which_alternative)
493 {
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 */
511 {
512 long bits;
513 rtx ops[4];
514
515 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
516 HFmode);
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);
521
522 if (arm_arch_thumb2)
523 output_asm_insn (\"movw\\t%0, %1\", ops);
524 else
525 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
526 return \"\";
527 }
528 default:
529 gcc_unreachable ();
530 }
531 "
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")]
536 )
537
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"))]
542 "TARGET_32BIT
543 && TARGET_HARD_FLOAT
544 && !TARGET_NEON_FP16
545 && !TARGET_VFP_FP16INST
546 && ( s_register_operand (operands[0], HFmode)
547 || s_register_operand (operands[1], HFmode))"
548 "*
549 switch (which_alternative)
550 {
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 */
564 {
565 long bits;
566 rtx ops[4];
567
568 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
569 HFmode);
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);
574
575 if (arm_arch_thumb2)
576 output_asm_insn (\"movw\\t%0, %1\", ops);
577 else
578 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
579 return \"\";
580 }
581 default:
582 gcc_unreachable ();
583 }
584 "
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")]
588 )
589
590
591 ;; SFmode moves
592 ;; Disparage the w<->r cases because reloading an invalid address is
593 ;; preferable to loading the value via integer registers.
594
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))"
601 "*
602 switch (which_alternative)
603 {
604 case 0:
605 return \"vmov%?\\t%0, %1\";
606 case 1:
607 return \"vmov%?\\t%0, %1\";
608 case 2:
609 return \"vmov%?.f32\\t%0, %1\";
610 case 3: case 4:
611 return output_move_vfp (operands);
612 case 5:
613 return \"ldr%?\\t%0, %1\\t%@ float\";
614 case 6:
615 return \"str%?\\t%1, %0\\t%@ float\";
616 case 7:
617 return \"vmov%?.f32\\t%0, %1\";
618 case 8:
619 return \"mov%?\\t%0, %1\\t%@ float\";
620 default:
621 gcc_unreachable ();
622 }
623 "
624 [(set_attr "predicable" "yes")
625 (set_attr "type"
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,*,*,*")]
629 )
630
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))"
637 "*
638 switch (which_alternative)
639 {
640 case 0:
641 return \"vmov%?\\t%0, %1\";
642 case 1:
643 return \"vmov%?\\t%0, %1\";
644 case 2:
645 return \"vmov%?.f32\\t%0, %1\";
646 case 3: case 4:
647 return output_move_vfp (operands);
648 case 5:
649 return \"ldr%?\\t%0, %1\\t%@ float\";
650 case 6:
651 return \"str%?\\t%1, %0\\t%@ float\";
652 case 7:
653 return \"vmov%?.f32\\t%0, %1\";
654 case 8:
655 return \"mov%?\\t%0, %1\\t%@ float\";
656 default:
657 gcc_unreachable ();
658 }
659 "
660 [(set_attr "predicable" "yes")
661 (set_attr "predicable_short_it" "no")
662 (set_attr "type"
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,*,*,*")]
666 )
667
668 ;; DFmode moves
669
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))"
676 "*
677 {
678 switch (which_alternative)
679 {
680 case 0:
681 return \"vmov%?\\t%P0, %Q1, %R1\";
682 case 1:
683 return \"vmov%?\\t%Q0, %R0, %P1\";
684 case 2:
685 gcc_assert (TARGET_VFP_DOUBLE);
686 return \"vmov%?.f64\\t%P0, %1\";
687 case 3:
688 gcc_assert (TARGET_VFP_DOUBLE);
689 return \"vmov.i64\\t%P0, #0\\t%@ float\";
690 case 4: case 5:
691 return output_move_vfp (operands);
692 case 6: case 7:
693 return output_move_double (operands, true, NULL);
694 case 8:
695 if (TARGET_VFP_SINGLE)
696 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
697 else
698 return \"vmov%?.f64\\t%P0, %P1\";
699 case 9:
700 return \"#\";
701 default:
702 gcc_unreachable ();
703 }
704 }
705 "
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")
710 (if_then_else
711 (match_test "TARGET_VFP_SINGLE")
712 (const_int 8)
713 (const_int 4))]
714 (const_int 4)))
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")]
719 )
720
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))"
727 "*
728 {
729 switch (which_alternative)
730 {
731 case 0:
732 return \"vmov%?\\t%P0, %Q1, %R1\";
733 case 1:
734 return \"vmov%?\\t%Q0, %R0, %P1\";
735 case 2:
736 gcc_assert (TARGET_VFP_DOUBLE);
737 return \"vmov%?.f64\\t%P0, %1\";
738 case 3:
739 gcc_assert (TARGET_VFP_DOUBLE);
740 return \"vmov.i64\\t%P0, #0\\t%@ float\";
741 case 4: case 5:
742 return output_move_vfp (operands);
743 case 6: case 7: case 9:
744 return output_move_double (operands, true, NULL);
745 case 8:
746 if (TARGET_VFP_SINGLE)
747 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
748 else
749 return \"vmov%?.f64\\t%P0, %P1\";
750 default:
751 abort ();
752 }
753 }
754 "
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")
759 (if_then_else
760 (match_test "TARGET_VFP_SINGLE")
761 (const_int 8)
762 (const_int 4))]
763 (const_int 4)))
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")]
767 )
768
769
770 ;; Conditional move patterns
771
772 (define_insn "*movsfcc_vfp"
773 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
774 (if_then_else:SF
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"
780 "@
781 vmov%D3.f32\\t%0, %2
782 vmov%d3.f32\\t%0, %1
783 vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
784 vmov%D3\\t%0, %2
785 vmov%d3\\t%0, %1
786 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
787 vmov%D3\\t%0, %2
788 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")]
793 )
794
795 (define_insn "*thumb2_movsfcc_vfp"
796 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
797 (if_then_else:SF
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"
803 "@
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")]
816 )
817
818 (define_insn "*movdfcc_vfp"
819 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
820 (if_then_else:DF
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"
826 "@
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")]
839 )
840
841 (define_insn "*thumb2_movdfcc_vfp"
842 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
843 (if_then_else:DF
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"
849 "@
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")]
862 )
863
864
865 ;; Sign manipulation functions
866
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")]
875 )
876
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")]
885 )
886
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"
891 "@
892 vneg%?.f32\\t%0, %1
893 eor%?\\t%0, %1, #-2147483648"
894 [(set_attr "predicable" "yes")
895 (set_attr "predicable_short_it" "no")
896 (set_attr "type" "ffariths")]
897 )
898
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"
903 "@
904 vneg%?.f64\\t%P0, %P1
905 #
906 #"
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))]
910 "
911 if (REGNO (operands[0]) == REGNO (operands[1]))
912 {
913 operands[0] = gen_highpart (SImode, operands[0]);
914 operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
915 }
916 else
917 {
918 rtx in_hi, in_lo, out_hi, out_lo;
919
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]);
925
926 if (REGNO (in_lo) == REGNO (out_hi))
927 {
928 emit_insn (gen_rtx_SET (out_lo, in_lo));
929 operands[0] = out_hi;
930 operands[1] = in_hi;
931 }
932 else
933 {
934 emit_insn (gen_rtx_SET (out_hi, in_hi));
935 operands[0] = out_lo;
936 operands[1] = in_lo;
937 }
938 }
939 "
940 [(set_attr "predicable" "yes")
941 (set_attr "predicable_short_it" "no")
942 (set_attr "length" "4,4,8")
943 (set_attr "type" "ffarithd")]
944 )
945
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")]
954 )
955
956 (define_expand "neon_vabshf"
957 [(set
958 (match_operand:HF 0 "s_register_operand")
959 (abs:HF (match_operand:HF 1 "s_register_operand")))]
960 "TARGET_VFP_FP16INST"
961 {
962 emit_insn (gen_abshf2 (operands[0], operands[1]));
963 DONE;
964 })
965
966 ;; VRND for FP16.
967 (define_insn "neon_v<fp16_rnd_str>hf"
968 [(set (match_operand:HF 0 "s_register_operand" "=w")
969 (unspec:HF
970 [(match_operand:HF 1 "s_register_operand" "w")]
971 FP16_RND))]
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")]
976 )
977
978 (define_insn "neon_vrndihf"
979 [(set (match_operand:HF 0 "s_register_operand" "=w")
980 (unspec:HF
981 [(match_operand:HF 1 "s_register_operand" "w")]
982 UNSPEC_VRNDI))]
983 "TARGET_VFP_FP16INST"
984 "vrintr.f16\t%0, %1"
985 [(set_attr "conds" "unconditional")
986 (set_attr "type" "neon_fp_round_s")]
987 )
988
989 ;; Arithmetic insns
990
991 (define_insn "addhf3"
992 [(set
993 (match_operand:HF 0 "s_register_operand" "=w")
994 (plus:HF
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")]
1001 )
1002
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")]
1012 )
1013
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")]
1023 )
1024
1025 (define_insn "subhf3"
1026 [(set
1027 (match_operand:HF 0 "s_register_operand" "=w")
1028 (minus:HF
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")]
1035 )
1036
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")]
1046 )
1047
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")]
1057 )
1058
1059
1060 ;; Division insns
1061
1062 ;; FP16 Division.
1063 (define_insn "divhf3"
1064 [(set
1065 (match_operand:HF 0 "s_register_operand" "=w")
1066 (div:HF
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")]
1073 )
1074
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
1077 ; earlier.
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")]
1088 )
1089
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")]
1100 )
1101
1102
1103 ;; Multiplication insns
1104
1105 (define_insn "mulhf3"
1106 [(set
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")]
1114 )
1115
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")]
1125 )
1126
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")]
1136 )
1137
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")]
1146 )
1147
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")]
1156 )
1157
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")]
1167 )
1168
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")]
1178 )
1179
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")]
1190 )
1191
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")]
1201 )
1202
1203
1204 ;; Multiply-accumulate insns
1205
1206 ;; 0 = 1 * 2 + 0
1207 (define_insn "*mulsf3addhf_vfp"
1208 [(set (match_operand:HF 0 "s_register_operand" "=t")
1209 (plus:HF
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")]
1217 )
1218
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")]
1229 )
1230
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")]
1241 )
1242
1243 ;; 0 = 1 * 2 - 0
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")]
1253 )
1254
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")]
1265 )
1266
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")]
1277 )
1278
1279 ;; 0 = -(1 * 2) + 0
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")]
1289 )
1290
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")]
1301 )
1302
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")]
1313 )
1314
1315
1316 ;; 0 = -(1 * 2) - 0
1317 (define_insn "*mulhf3neghfsubhf_vfp"
1318 [(set (match_operand:HF 0 "s_register_operand" "=t")
1319 (minus:HF (mult:HF
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")]
1327 )
1328
1329 (define_insn "*mulsf3negsfsubsf_vfp"
1330 [(set (match_operand:SF 0 "s_register_operand" "=t")
1331 (minus:SF (mult:SF
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")]
1340 )
1341
1342 (define_insn "*muldf3negdfsubdf_vfp"
1343 [(set (match_operand:DF 0 "s_register_operand" "=w")
1344 (minus:DF (mult:DF
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")]
1353 )
1354
1355 ;; Fused-multiply-accumulate
1356
1357 (define_insn "fmahf4"
1358 [(set (match_operand:HF 0 "register_operand" "=w")
1359 (fma:HF
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")]
1367 )
1368
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"
1375 {
1376 emit_insn (gen_fmahf4 (operands[0], operands[2], operands[3],
1377 operands[1]));
1378 DONE;
1379 })
1380
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>")]
1391 )
1392
1393 (define_insn "fmsubhf4_fp16"
1394 [(set (match_operand:HF 0 "register_operand" "=w")
1395 (fma:HF
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")]
1403 )
1404
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"
1411 {
1412 emit_insn (gen_fmsubhf4_fp16 (operands[0], operands[2], operands[3],
1413 operands[1]));
1414 DONE;
1415 })
1416
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"
1420 "<F_constraint>"))
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>")]
1428 )
1429
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")]
1439 )
1440
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>")]
1451 )
1452
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")]
1462 )
1463
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"
1467 "<F_constraint>"))
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>")]
1475 )
1476
1477
1478 ;; Conversion routines
1479
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")]
1488 )
1489
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")]
1498 )
1499
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")]
1508 )
1509
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")]
1518 )
1519
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")]
1528 )
1529
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")]
1538 )
1539
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")]
1548 )
1549
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")]
1558 )
1559
1560
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")]
1569 )
1570
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")]
1579 )
1580
1581
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")]
1590 )
1591
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")]
1600 )
1601
1602
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")]
1611 )
1612
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")]
1621 )
1622
1623
1624 ;; Sqrt insns.
1625
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"
1630 "vsqrt.f16\t%0, %1"
1631 [(set_attr "conds" "unconditional")
1632 (set_attr "type" "fsqrts")]
1633 )
1634
1635 (define_insn "neon_vrsqrtshf"
1636 [(set
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")]
1640 UNSPEC_VRSQRTS))]
1641 "TARGET_VFP_FP16INST"
1642 "vrsqrts.f16\t%0, %1, %2"
1643 [(set_attr "conds" "unconditional")
1644 (set_attr "type" "fsqrts")]
1645 )
1646
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
1649 ; earlier.
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")]
1659 )
1660
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")]
1670 )
1671
1672
1673 ;; Patterns to split/copy vfp condition flags.
1674
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")]
1682 )
1683
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"
1689 "#"
1690 "TARGET_32BIT && TARGET_HARD_FLOAT"
1691 [(set (reg:CCFP VFPCC_REGNUM)
1692 (compare:CCFP (match_dup 0)
1693 (match_dup 1)))
1694 (set (reg:CCFP CC_REGNUM)
1695 (reg:CCFP VFPCC_REGNUM))]
1696 ""
1697 )
1698
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"
1704 "#"
1705 "TARGET_32BIT && TARGET_HARD_FLOAT"
1706 [(set (reg:CCFPE VFPCC_REGNUM)
1707 (compare:CCFPE (match_dup 0)
1708 (match_dup 1)))
1709 (set (reg:CCFPE CC_REGNUM)
1710 (reg:CCFPE VFPCC_REGNUM))]
1711 ""
1712 )
1713
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"
1719 "#"
1720 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1721 [(set (reg:CCFP VFPCC_REGNUM)
1722 (compare:CCFP (match_dup 0)
1723 (match_dup 1)))
1724 (set (reg:CCFP CC_REGNUM)
1725 (reg:CCFP VFPCC_REGNUM))]
1726 ""
1727 )
1728
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"
1734 "#"
1735 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1736 [(set (reg:CCFPE VFPCC_REGNUM)
1737 (compare:CCFPE (match_dup 0)
1738 (match_dup 1)))
1739 (set (reg:CCFPE CC_REGNUM)
1740 (reg:CCFPE VFPCC_REGNUM))]
1741 ""
1742 )
1743
1744
1745 ;; Comparison patterns
1746
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"
1755 "@
1756 vcmp%?.f32\\t%0, %1
1757 vcmp%?.f32\\t%0, #0"
1758 [(set_attr "predicable" "yes")
1759 (set_attr "predicable_short_it" "no")
1760 (set_attr "type" "fcmps")]
1761 )
1762
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"
1768 "@
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")]
1774 )
1775
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"
1781 "@
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")]
1787 )
1788
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"
1794 "@
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")]
1800 )
1801
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"))
1806 (match_operand 2
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")]
1813 )
1814
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"))
1820 (match_operand 2
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"
1824 "@
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")]
1833 )
1834
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")
1838 (match_operand 2
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")]
1845 )
1846
1847 ;; FP16 conversions.
1848 (define_insn "neon_vcvth<sup>hf"
1849 [(set (match_operand:HF 0 "s_register_operand" "=w")
1850 (unspec:HF
1851 [(match_operand:SI 1 "s_register_operand" "w")]
1852 VCVTH_US))]
1853 "TARGET_VFP_FP16INST"
1854 "vcvt.f16.<sup>%#32\t%0, %1"
1855 [(set_attr "conds" "unconditional")
1856 (set_attr "type" "f_cvti2f")]
1857 )
1858
1859 (define_insn "neon_vcvth<sup>si"
1860 [(set (match_operand:SI 0 "s_register_operand" "=w")
1861 (unspec:SI
1862 [(match_operand:HF 1 "s_register_operand" "w")]
1863 VCVTH_US))]
1864 "TARGET_VFP_FP16INST"
1865 "vcvt.<sup>%#32.f16\t%0, %1"
1866 [(set_attr "conds" "unconditional")
1867 (set_attr "type" "f_cvtf2i")]
1868 )
1869
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.
1875
1876 ;; Generate an unspec pattern for the intrinsic.
1877 (define_insn "neon_vcvth<sup>_nhf_unspec"
1878 [(set
1879 (match_operand:SI 0 "s_register_operand" "=w")
1880 (unspec:SI
1881 [(match_operand:SI 1 "s_register_operand" "0")
1882 (match_operand:SI 2 "immediate_operand" "i")]
1883 VCVT_HF_US_N))
1884 (set
1885 (match_operand:HF 3 "s_register_operand" "=w")
1886 (float_truncate:HF (float:SF (match_dup 0))))]
1887 "TARGET_VFP_FP16INST"
1888 {
1889 arm_const_bounds (operands[2], 1, 33);
1890 return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1891 }
1892 [(set_attr "conds" "unconditional")
1893 (set_attr "type" "f_cvti2f")]
1894 )
1895
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")]
1901 VCVT_HF_US_N)]
1902 "TARGET_VFP_FP16INST"
1903 {
1904 rtx op1 = gen_reg_rtx (SImode);
1905
1906 arm_const_bounds (operands[2], 1, 33);
1907
1908 emit_move_insn (op1, operands[1]);
1909 emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2],
1910 operands[0]));
1911 DONE;
1912 })
1913
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.
1917
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")
1921 (unspec:SI
1922 [(fix:SI
1923 (fix:SF
1924 (float_extend:SF
1925 (match_operand:HF 1 "s_register_operand" "w"))))
1926 (match_operand:SI 2 "immediate_operand" "i")]
1927 VCVT_SI_US_N))]
1928 "TARGET_VFP_FP16INST"
1929 {
1930 arm_const_bounds (operands[2], 1, 33);
1931 return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1932 }
1933 [(set_attr "conds" "unconditional")
1934 (set_attr "type" "f_cvtf2i")]
1935 )
1936
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")
1940 (unspec:SI
1941 [(match_operand:HF 1 "s_register_operand")
1942 (match_operand:SI 2 "immediate_operand")]
1943 VCVT_SI_US_N)]
1944 "TARGET_VFP_FP16INST"
1945 {
1946 rtx op1 = gen_reg_rtx (SImode);
1947
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);
1951 DONE;
1952 })
1953
1954 (define_insn "neon_vcvt<vcvth_op>h<sup>si"
1955 [(set
1956 (match_operand:SI 0 "s_register_operand" "=w")
1957 (unspec:SI
1958 [(match_operand:HF 1 "s_register_operand" "w")]
1959 VCVT_HF_US))]
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")]
1964 )
1965
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")]
1975 )
1976
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>")]
1985 VRINT))]
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>")]
1992 )
1993
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")]
2005 )
2006
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
2012 ;; NaNs.
2013
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")]
2022 )
2023
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")]
2032 )
2033
2034 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
2035
2036 (define_insn "neon_<fmaxmin_op>hf"
2037 [(set
2038 (match_operand:HF 0 "s_register_operand" "=w")
2039 (unspec:HF
2040 [(match_operand:HF 1 "s_register_operand" "w")
2041 (match_operand:HF 2 "s_register_operand" "w")]
2042 VMAXMINFNM))]
2043 "TARGET_VFP_FP16INST"
2044 "<fmaxmin_op>.f16\t%0, %1, %2"
2045 [(set_attr "conds" "unconditional")
2046 (set_attr "type" "f_minmaxs")]
2047 )
2048
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>")]
2053 VMAXMINFNM))]
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")]
2058 )
2059
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)]
2063 "TARGET_HARD_FLOAT"
2064 "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
2065 [(set_attr "type" "mrs")])
2066
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))]
2071 "TARGET_HARD_FLOAT"
2072 "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
2073 [(set_attr "type" "mrs")])
2074
2075
2076 ;; Unimplemented insns:
2077 ;; fldm*
2078 ;; fstm*
2079 ;; fmdhr et al (VFPv1)
2080 ;; Support for xD (single precision only) variants.
2081 ;; fmrrs, fmsrr