]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/vfp.md
[ARM] Remove duplicated enum type for CPU identifiers
[thirdparty/gcc.git] / gcc / config / arm / vfp.md
1 ;; ARM VFP instruction patterns
2 ;; Copyright (C) 2003-2016 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,r,r,m,w,!r,w,w, Uv")
359 (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,r,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 "truncsfhf2"
1511 [(set (match_operand:HF 0 "s_register_operand" "=t")
1512 (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
1513 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1514 "vcvtb%?.f16.f32\\t%0, %1"
1515 [(set_attr "predicable" "yes")
1516 (set_attr "predicable_short_it" "no")
1517 (set_attr "type" "f_cvt")]
1518 )
1519
1520 (define_insn "*truncsisf2_vfp"
1521 [(set (match_operand:SI 0 "s_register_operand" "=t")
1522 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1523 "TARGET_32BIT && TARGET_HARD_FLOAT"
1524 "vcvt%?.s32.f32\\t%0, %1"
1525 [(set_attr "predicable" "yes")
1526 (set_attr "predicable_short_it" "no")
1527 (set_attr "type" "f_cvtf2i")]
1528 )
1529
1530 (define_insn "*truncsidf2_vfp"
1531 [(set (match_operand:SI 0 "s_register_operand" "=t")
1532 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
1533 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1534 "vcvt%?.s32.f64\\t%0, %P1"
1535 [(set_attr "predicable" "yes")
1536 (set_attr "predicable_short_it" "no")
1537 (set_attr "type" "f_cvtf2i")]
1538 )
1539
1540
1541 (define_insn "fixuns_truncsfsi2"
1542 [(set (match_operand:SI 0 "s_register_operand" "=t")
1543 (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1544 "TARGET_32BIT && TARGET_HARD_FLOAT"
1545 "vcvt%?.u32.f32\\t%0, %1"
1546 [(set_attr "predicable" "yes")
1547 (set_attr "predicable_short_it" "no")
1548 (set_attr "type" "f_cvtf2i")]
1549 )
1550
1551 (define_insn "fixuns_truncdfsi2"
1552 [(set (match_operand:SI 0 "s_register_operand" "=t")
1553 (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
1554 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1555 "vcvt%?.u32.f64\\t%0, %P1"
1556 [(set_attr "predicable" "yes")
1557 (set_attr "predicable_short_it" "no")
1558 (set_attr "type" "f_cvtf2i")]
1559 )
1560
1561
1562 (define_insn "*floatsisf2_vfp"
1563 [(set (match_operand:SF 0 "s_register_operand" "=t")
1564 (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1565 "TARGET_32BIT && TARGET_HARD_FLOAT"
1566 "vcvt%?.f32.s32\\t%0, %1"
1567 [(set_attr "predicable" "yes")
1568 (set_attr "predicable_short_it" "no")
1569 (set_attr "type" "f_cvti2f")]
1570 )
1571
1572 (define_insn "*floatsidf2_vfp"
1573 [(set (match_operand:DF 0 "s_register_operand" "=w")
1574 (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1575 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1576 "vcvt%?.f64.s32\\t%P0, %1"
1577 [(set_attr "predicable" "yes")
1578 (set_attr "predicable_short_it" "no")
1579 (set_attr "type" "f_cvti2f")]
1580 )
1581
1582
1583 (define_insn "floatunssisf2"
1584 [(set (match_operand:SF 0 "s_register_operand" "=t")
1585 (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1586 "TARGET_32BIT && TARGET_HARD_FLOAT"
1587 "vcvt%?.f32.u32\\t%0, %1"
1588 [(set_attr "predicable" "yes")
1589 (set_attr "predicable_short_it" "no")
1590 (set_attr "type" "f_cvti2f")]
1591 )
1592
1593 (define_insn "floatunssidf2"
1594 [(set (match_operand:DF 0 "s_register_operand" "=w")
1595 (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1596 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1597 "vcvt%?.f64.u32\\t%P0, %1"
1598 [(set_attr "predicable" "yes")
1599 (set_attr "predicable_short_it" "no")
1600 (set_attr "type" "f_cvti2f")]
1601 )
1602
1603
1604 ;; Sqrt insns.
1605
1606 (define_insn "neon_vsqrthf"
1607 [(set (match_operand:HF 0 "s_register_operand" "=w")
1608 (sqrt:HF (match_operand:HF 1 "s_register_operand" "w")))]
1609 "TARGET_VFP_FP16INST"
1610 "vsqrt.f16\t%0, %1"
1611 [(set_attr "conds" "unconditional")
1612 (set_attr "type" "fsqrts")]
1613 )
1614
1615 (define_insn "neon_vrsqrtshf"
1616 [(set
1617 (match_operand:HF 0 "s_register_operand" "=w")
1618 (unspec:HF [(match_operand:HF 1 "s_register_operand" "w")
1619 (match_operand:HF 2 "s_register_operand" "w")]
1620 UNSPEC_VRSQRTS))]
1621 "TARGET_VFP_FP16INST"
1622 "vrsqrts.f16\t%0, %1, %2"
1623 [(set_attr "conds" "unconditional")
1624 (set_attr "type" "fsqrts")]
1625 )
1626
1627 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1628 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1629 ; earlier.
1630 (define_insn "*sqrtsf2_vfp"
1631 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1632 (sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))]
1633 "TARGET_32BIT && TARGET_HARD_FLOAT"
1634 "vsqrt%?.f32\\t%0, %1"
1635 [(set_attr "predicable" "yes")
1636 (set_attr "predicable_short_it" "no")
1637 (set_attr "arch" "*,armv6_or_vfpv3")
1638 (set_attr "type" "fsqrts")]
1639 )
1640
1641 (define_insn "*sqrtdf2_vfp"
1642 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1643 (sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))]
1644 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1645 "vsqrt%?.f64\\t%P0, %P1"
1646 [(set_attr "predicable" "yes")
1647 (set_attr "predicable_short_it" "no")
1648 (set_attr "arch" "*,armv6_or_vfpv3")
1649 (set_attr "type" "fsqrtd")]
1650 )
1651
1652
1653 ;; Patterns to split/copy vfp condition flags.
1654
1655 (define_insn "*movcc_vfp"
1656 [(set (reg CC_REGNUM)
1657 (reg VFPCC_REGNUM))]
1658 "TARGET_32BIT && TARGET_HARD_FLOAT"
1659 "vmrs%?\\tAPSR_nzcv, FPSCR"
1660 [(set_attr "conds" "set")
1661 (set_attr "type" "f_flag")]
1662 )
1663
1664 (define_insn_and_split "*cmpsf_split_vfp"
1665 [(set (reg:CCFP CC_REGNUM)
1666 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t")
1667 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1668 "TARGET_32BIT && TARGET_HARD_FLOAT"
1669 "#"
1670 "TARGET_32BIT && TARGET_HARD_FLOAT"
1671 [(set (reg:CCFP VFPCC_REGNUM)
1672 (compare:CCFP (match_dup 0)
1673 (match_dup 1)))
1674 (set (reg:CCFP CC_REGNUM)
1675 (reg:CCFP VFPCC_REGNUM))]
1676 ""
1677 )
1678
1679 (define_insn_and_split "*cmpsf_trap_split_vfp"
1680 [(set (reg:CCFPE CC_REGNUM)
1681 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t")
1682 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1683 "TARGET_32BIT && TARGET_HARD_FLOAT"
1684 "#"
1685 "TARGET_32BIT && TARGET_HARD_FLOAT"
1686 [(set (reg:CCFPE VFPCC_REGNUM)
1687 (compare:CCFPE (match_dup 0)
1688 (match_dup 1)))
1689 (set (reg:CCFPE CC_REGNUM)
1690 (reg:CCFPE VFPCC_REGNUM))]
1691 ""
1692 )
1693
1694 (define_insn_and_split "*cmpdf_split_vfp"
1695 [(set (reg:CCFP CC_REGNUM)
1696 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
1697 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1698 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1699 "#"
1700 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1701 [(set (reg:CCFP VFPCC_REGNUM)
1702 (compare:CCFP (match_dup 0)
1703 (match_dup 1)))
1704 (set (reg:CCFP CC_REGNUM)
1705 (reg:CCFP VFPCC_REGNUM))]
1706 ""
1707 )
1708
1709 (define_insn_and_split "*cmpdf_trap_split_vfp"
1710 [(set (reg:CCFPE CC_REGNUM)
1711 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
1712 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1713 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1714 "#"
1715 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1716 [(set (reg:CCFPE VFPCC_REGNUM)
1717 (compare:CCFPE (match_dup 0)
1718 (match_dup 1)))
1719 (set (reg:CCFPE CC_REGNUM)
1720 (reg:CCFPE VFPCC_REGNUM))]
1721 ""
1722 )
1723
1724
1725 ;; Comparison patterns
1726
1727 ;; In the compare with FP zero case the ARM Architecture Reference Manual
1728 ;; specifies the immediate to be #0.0. However, some buggy assemblers only
1729 ;; accept #0. We don't want to autodetect broken assemblers, so output #0.
1730 (define_insn "*cmpsf_vfp"
1731 [(set (reg:CCFP VFPCC_REGNUM)
1732 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t,t")
1733 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1734 "TARGET_32BIT && TARGET_HARD_FLOAT"
1735 "@
1736 vcmp%?.f32\\t%0, %1
1737 vcmp%?.f32\\t%0, #0"
1738 [(set_attr "predicable" "yes")
1739 (set_attr "predicable_short_it" "no")
1740 (set_attr "type" "fcmps")]
1741 )
1742
1743 (define_insn "*cmpsf_trap_vfp"
1744 [(set (reg:CCFPE VFPCC_REGNUM)
1745 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t,t")
1746 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1747 "TARGET_32BIT && TARGET_HARD_FLOAT"
1748 "@
1749 vcmpe%?.f32\\t%0, %1
1750 vcmpe%?.f32\\t%0, #0"
1751 [(set_attr "predicable" "yes")
1752 (set_attr "predicable_short_it" "no")
1753 (set_attr "type" "fcmps")]
1754 )
1755
1756 (define_insn "*cmpdf_vfp"
1757 [(set (reg:CCFP VFPCC_REGNUM)
1758 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
1759 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1760 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1761 "@
1762 vcmp%?.f64\\t%P0, %P1
1763 vcmp%?.f64\\t%P0, #0"
1764 [(set_attr "predicable" "yes")
1765 (set_attr "predicable_short_it" "no")
1766 (set_attr "type" "fcmpd")]
1767 )
1768
1769 (define_insn "*cmpdf_trap_vfp"
1770 [(set (reg:CCFPE VFPCC_REGNUM)
1771 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
1772 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1773 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1774 "@
1775 vcmpe%?.f64\\t%P0, %P1
1776 vcmpe%?.f64\\t%P0, #0"
1777 [(set_attr "predicable" "yes")
1778 (set_attr "predicable_short_it" "no")
1779 (set_attr "type" "fcmpd")]
1780 )
1781
1782 ;; Fixed point to floating point conversions.
1783 (define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1784 [(set (match_operand:SF 0 "s_register_operand" "=t")
1785 (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
1786 (match_operand 2
1787 "const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1788 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1789 "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2"
1790 [(set_attr "predicable" "yes")
1791 (set_attr "predicable_short_it" "no")
1792 (set_attr "type" "f_cvti2f")]
1793 )
1794
1795 ;; Not the ideal way of implementing this. Ideally we would be able to split
1796 ;; this into a move to a DP register and then a vcvt.f64.i32
1797 (define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1798 [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1799 (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
1800 (match_operand 2
1801 "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
1802 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
1803 && !TARGET_VFP_SINGLE"
1804 "@
1805 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1806 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1807 vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1808 [(set_attr "predicable" "yes")
1809 (set_attr "ce_count" "2")
1810 (set_attr "predicable_short_it" "no")
1811 (set_attr "type" "f_cvti2f")
1812 (set_attr "length" "8")]
1813 )
1814
1815 (define_insn "*combine_vcvtf2i"
1816 [(set (match_operand:SI 0 "s_register_operand" "=t")
1817 (fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0")
1818 (match_operand 2
1819 "const_double_vcvt_power_of_two" "Dp")))))]
1820 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1821 "vcvt%?.s32.f32\\t%0, %1, %v2"
1822 [(set_attr "predicable" "yes")
1823 (set_attr "predicable_short_it" "no")
1824 (set_attr "type" "f_cvtf2i")]
1825 )
1826
1827 ;; FP16 conversions.
1828 (define_insn "neon_vcvth<sup>hf"
1829 [(set (match_operand:HF 0 "s_register_operand" "=w")
1830 (unspec:HF
1831 [(match_operand:SI 1 "s_register_operand" "w")]
1832 VCVTH_US))]
1833 "TARGET_VFP_FP16INST"
1834 "vcvt.f16.<sup>%#32\t%0, %1"
1835 [(set_attr "conds" "unconditional")
1836 (set_attr "type" "f_cvti2f")]
1837 )
1838
1839 (define_insn "neon_vcvth<sup>si"
1840 [(set (match_operand:SI 0 "s_register_operand" "=w")
1841 (unspec:SI
1842 [(match_operand:HF 1 "s_register_operand" "w")]
1843 VCVTH_US))]
1844 "TARGET_VFP_FP16INST"
1845 "vcvt.<sup>%#32.f16\t%0, %1"
1846 [(set_attr "conds" "unconditional")
1847 (set_attr "type" "f_cvtf2i")]
1848 )
1849
1850 ;; The neon_vcvth<sup>_nhf patterns are used to generate the instruction for the
1851 ;; vcvth_n_f16_<sup>32 arm_fp16 intrinsics. They are complicated by the
1852 ;; hardware requirement that the source and destination registers are the same
1853 ;; despite having different machine modes. The approach is to use a temporary
1854 ;; register for the conversion and move that to the correct destination.
1855
1856 ;; Generate an unspec pattern for the intrinsic.
1857 (define_insn "neon_vcvth<sup>_nhf_unspec"
1858 [(set
1859 (match_operand:SI 0 "s_register_operand" "=w")
1860 (unspec:SI
1861 [(match_operand:SI 1 "s_register_operand" "0")
1862 (match_operand:SI 2 "immediate_operand" "i")]
1863 VCVT_HF_US_N))
1864 (set
1865 (match_operand:HF 3 "s_register_operand" "=w")
1866 (float_truncate:HF (float:SF (match_dup 0))))]
1867 "TARGET_VFP_FP16INST"
1868 {
1869 neon_const_bounds (operands[2], 1, 33);
1870 return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1871 }
1872 [(set_attr "conds" "unconditional")
1873 (set_attr "type" "f_cvti2f")]
1874 )
1875
1876 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1877 (define_expand "neon_vcvth<sup>_nhf"
1878 [(match_operand:HF 0 "s_register_operand")
1879 (unspec:HF [(match_operand:SI 1 "s_register_operand")
1880 (match_operand:SI 2 "immediate_operand")]
1881 VCVT_HF_US_N)]
1882 "TARGET_VFP_FP16INST"
1883 {
1884 rtx op1 = gen_reg_rtx (SImode);
1885
1886 neon_const_bounds (operands[2], 1, 33);
1887
1888 emit_move_insn (op1, operands[1]);
1889 emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2],
1890 operands[0]));
1891 DONE;
1892 })
1893
1894 ;; The neon_vcvth<sup>_nsi patterns are used to generate the instruction for the
1895 ;; vcvth_n_<sup>32_f16 arm_fp16 intrinsics. They have the same restrictions and
1896 ;; are implemented in the same way as the neon_vcvth<sup>_nhf patterns.
1897
1898 ;; Generate an unspec pattern, constraining the registers.
1899 (define_insn "neon_vcvth<sup>_nsi_unspec"
1900 [(set (match_operand:SI 0 "s_register_operand" "=w")
1901 (unspec:SI
1902 [(fix:SI
1903 (fix:SF
1904 (float_extend:SF
1905 (match_operand:HF 1 "s_register_operand" "w"))))
1906 (match_operand:SI 2 "immediate_operand" "i")]
1907 VCVT_SI_US_N))]
1908 "TARGET_VFP_FP16INST"
1909 {
1910 neon_const_bounds (operands[2], 1, 33);
1911 return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1912 }
1913 [(set_attr "conds" "unconditional")
1914 (set_attr "type" "f_cvtf2i")]
1915 )
1916
1917 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1918 (define_expand "neon_vcvth<sup>_nsi"
1919 [(match_operand:SI 0 "s_register_operand")
1920 (unspec:SI
1921 [(match_operand:HF 1 "s_register_operand")
1922 (match_operand:SI 2 "immediate_operand")]
1923 VCVT_SI_US_N)]
1924 "TARGET_VFP_FP16INST"
1925 {
1926 rtx op1 = gen_reg_rtx (SImode);
1927
1928 neon_const_bounds (operands[2], 1, 33);
1929 emit_insn (gen_neon_vcvth<sup>_nsi_unspec (op1, operands[1], operands[2]));
1930 emit_move_insn (operands[0], op1);
1931 DONE;
1932 })
1933
1934 (define_insn "neon_vcvt<vcvth_op>h<sup>si"
1935 [(set
1936 (match_operand:SI 0 "s_register_operand" "=w")
1937 (unspec:SI
1938 [(match_operand:HF 1 "s_register_operand" "w")]
1939 VCVT_HF_US))]
1940 "TARGET_VFP_FP16INST"
1941 "vcvt<vcvth_op>.<sup>%#32.f16\t%0, %1"
1942 [(set_attr "conds" "unconditional")
1943 (set_attr "type" "f_cvtf2i")]
1944 )
1945
1946 ;; Store multiple insn used in function prologue.
1947 (define_insn "*push_multi_vfp"
1948 [(match_parallel 2 "multi_register_push"
1949 [(set (match_operand:BLK 0 "memory_operand" "=m")
1950 (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
1951 UNSPEC_PUSH_MULT))])]
1952 "TARGET_32BIT && TARGET_HARD_FLOAT"
1953 "* return vfp_output_vstmd (operands);"
1954 [(set_attr "type" "f_stored")]
1955 )
1956
1957 ;; VRINT round to integral instructions.
1958 ;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
1959 ;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
1960 ;; rintsf2, rintdf2.
1961 (define_insn "<vrint_pattern><SDF:mode>2"
1962 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1963 (unspec:SDF [(match_operand:SDF 1
1964 "register_operand" "<F_constraint>")]
1965 VRINT))]
1966 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1967 "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
1968 [(set_attr "predicable" "<vrint_predicable>")
1969 (set_attr "predicable_short_it" "no")
1970 (set_attr "type" "f_rint<vfp_type>")
1971 (set_attr "conds" "<vrint_conds>")]
1972 )
1973
1974 ;; Implements the lround, lfloor and lceil optabs.
1975 (define_insn "l<vrint_pattern><su_optab><mode>si2"
1976 [(set (match_operand:SI 0 "register_operand" "=t")
1977 (FIXUORS:SI (unspec:SDF
1978 [(match_operand:SDF 1
1979 "register_operand" "<F_constraint>")] VCVT)))]
1980 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
1981 "vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1"
1982 [(set_attr "predicable" "no")
1983 (set_attr "conds" "unconditional")
1984 (set_attr "type" "f_cvtf2i")]
1985 )
1986
1987 ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
1988 ;; The 'smax' and 'smin' RTL standard pattern names do not specify which
1989 ;; operand will be returned when both operands are zero (i.e. they may not
1990 ;; honour signed zeroes), or when either operand is NaN. Therefore GCC
1991 ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
1992 ;; NaNs.
1993
1994 (define_insn "smax<mode>3"
1995 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1996 (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1997 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1998 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1999 "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2000 [(set_attr "type" "f_minmax<vfp_type>")
2001 (set_attr "conds" "unconditional")]
2002 )
2003
2004 (define_insn "smin<mode>3"
2005 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
2006 (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
2007 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
2008 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2009 "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2010 [(set_attr "type" "f_minmax<vfp_type>")
2011 (set_attr "conds" "unconditional")]
2012 )
2013
2014 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
2015
2016 (define_insn "neon_<fmaxmin_op>hf"
2017 [(set
2018 (match_operand:HF 0 "s_register_operand" "=w")
2019 (unspec:HF
2020 [(match_operand:HF 1 "s_register_operand" "w")
2021 (match_operand:HF 2 "s_register_operand" "w")]
2022 VMAXMINFNM))]
2023 "TARGET_VFP_FP16INST"
2024 "<fmaxmin_op>.f16\t%0, %1, %2"
2025 [(set_attr "conds" "unconditional")
2026 (set_attr "type" "f_minmaxs")]
2027 )
2028
2029 (define_insn "<fmaxmin><mode>3"
2030 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
2031 (unspec:SDF [(match_operand:SDF 1 "s_register_operand" "<F_constraint>")
2032 (match_operand:SDF 2 "s_register_operand" "<F_constraint>")]
2033 VMAXMINFNM))]
2034 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2035 "<fmaxmin_op>.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2036 [(set_attr "type" "f_minmax<vfp_type>")
2037 (set_attr "conds" "unconditional")]
2038 )
2039
2040 ;; Write Floating-point Status and Control Register.
2041 (define_insn "set_fpscr"
2042 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)]
2043 "TARGET_HARD_FLOAT"
2044 "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
2045 [(set_attr "type" "mrs")])
2046
2047 ;; Read Floating-point Status and Control Register.
2048 (define_insn "get_fpscr"
2049 [(set (match_operand:SI 0 "register_operand" "=r")
2050 (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
2051 "TARGET_HARD_FLOAT"
2052 "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
2053 [(set_attr "type" "mrs")])
2054
2055
2056 ;; Unimplemented insns:
2057 ;; fldm*
2058 ;; fstm*
2059 ;; fmdhr et al (VFPv1)
2060 ;; Support for xD (single precision only) variants.
2061 ;; fmrrs, fmsrr