]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/vfp.md
backport: unnecessary duplication and repeating bugs like PR78439 due to changes...
[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 "store_4")
64 (const_string "load_4")
65 (const_string "f_mcr")
66 (const_string "f_mrc")
67 (const_string "fmov")])
68 (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
69 (set_attr "pool_range" "*, *, *, *, 256, *, *, *")
70 (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *")
71 (set_attr "length" "4")]
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, store_4, load_4,\
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 "store_4")
160 (const_string "load_4")
161 (const_string "f_mcr")
162 (const_string "f_mrc")
163 (const_string "fmov")])
164 (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
165 (set_attr "pool_range" "*, *, *, *, 256, *, *, *")
166 (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *")
167 (set_attr "length" "4")]
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, store_4, load_4,\
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,load_4,store_4,
250 f_mcr,f_mrc,fmov,f_loads,f_stores")
251 (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*")
252 (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")]
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,load_4,load_4,store_4,store_4,f_mcr,f_mrc,fmov,f_loads,f_stores")
298 (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4")
299 (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*")
300 (set_attr "neg_pool_range" "*,*,*,*,*, 0, 0,*,*,*,*,*,1008,*")]
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
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,load_8,load_8,store_8,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored")
342 (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8)
343 (eq_attr "alternative" "2") (const_int 12)
344 (eq_attr "alternative" "3") (const_int 16)
345 (eq_attr "alternative" "4,5,6")
346 (symbol_ref "arm_count_output_move_double_insns (operands) * 4")
347 (eq_attr "alternative" "9")
348 (if_then_else
349 (match_test "TARGET_VFP_SINGLE")
350 (const_int 8)
351 (const_int 4))]
352 (const_int 4)))
353 (set_attr "predicable" "yes")
354 (set_attr "arm_pool_range" "*,*,*,*,1020,4096,*,*,*,*,1020,*")
355 (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
356 (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
357 (set (attr "ce_count") (symbol_ref "get_attr_length (insn) / 4"))
358 (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
359 )
360
361 ;; HFmode moves
362
363 (define_insn "*movhf_vfp_fp16"
364 [(set (match_operand:HF 0 "nonimmediate_operand"
365 "= r,m,t,r,t,r,t,t,Um,r")
366 (match_operand:HF 1 "general_operand"
367 " m,r,t,r,r,t,Dv,Um,t,F"))]
368 "TARGET_32BIT
369 && TARGET_VFP_FP16INST
370 && (s_register_operand (operands[0], HFmode)
371 || s_register_operand (operands[1], HFmode))"
372 {
373 switch (which_alternative)
374 {
375 case 0: /* ARM register from memory. */
376 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
377 case 1: /* Memory from ARM register. */
378 return \"strh%?\\t%1, %0\\t%@ __fp16\";
379 case 2: /* S register from S register. */
380 return \"vmov\\t%0, %1\t%@ __fp16\";
381 case 3: /* ARM register from ARM register. */
382 return \"mov%?\\t%0, %1\\t%@ __fp16\";
383 case 4: /* S register from ARM register. */
384 case 5: /* ARM register from S register. */
385 case 6: /* S register from immediate. */
386 return \"vmov.f16\\t%0, %1\t%@ __fp16\";
387 case 7: /* S register from memory. */
388 return \"vld1.16\\t{%z0}, %A1\";
389 case 8: /* Memory from S register. */
390 return \"vst1.16\\t{%z1}, %A0\";
391 case 9: /* ARM register from constant. */
392 {
393 long bits;
394 rtx ops[4];
395
396 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
397 HFmode);
398 ops[0] = operands[0];
399 ops[1] = GEN_INT (bits);
400 ops[2] = GEN_INT (bits & 0xff00);
401 ops[3] = GEN_INT (bits & 0x00ff);
402
403 if (arm_arch_thumb2)
404 output_asm_insn (\"movw\\t%0, %1\", ops);
405 else
406 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
407 return \"\";
408 }
409 default:
410 gcc_unreachable ();
411 }
412 }
413 [(set_attr "predicable" "yes, yes, no, yes, no, no, no, no, no, no")
414 (set_attr "predicable_short_it" "no, no, no, yes,\
415 no, no, no, no,\
416 no, no")
417 (set_attr_alternative "type"
418 [(const_string "load_4") (const_string "store_4")
419 (const_string "fmov") (const_string "mov_reg")
420 (const_string "f_mcr") (const_string "f_mrc")
421 (const_string "fconsts") (const_string "neon_load1_1reg")
422 (const_string "neon_store1_1reg")
423 (if_then_else (match_test "arm_arch_thumb2")
424 (const_string "mov_imm")
425 (const_string "multiple"))])
426 (set_attr_alternative "length"
427 [(const_int 4) (const_int 4)
428 (const_int 4) (const_int 4)
429 (const_int 4) (const_int 4)
430 (const_int 4) (const_int 4)
431 (const_int 4)
432 (if_then_else (match_test "arm_arch_thumb2")
433 (const_int 4)
434 (const_int 8))])]
435 )
436
437 (define_insn "*movhf_vfp_neon"
438 [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r")
439 (match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))]
440 "TARGET_32BIT
441 && TARGET_HARD_FLOAT && TARGET_NEON_FP16
442 && !TARGET_VFP_FP16INST
443 && ( s_register_operand (operands[0], HFmode)
444 || s_register_operand (operands[1], HFmode))"
445 "*
446 switch (which_alternative)
447 {
448 case 0: /* S register from memory */
449 return \"vld1.16\\t{%z0}, %A1\";
450 case 1: /* memory from S register */
451 return \"vst1.16\\t{%z1}, %A0\";
452 case 2: /* ARM register from memory */
453 return \"ldrh\\t%0, %1\\t%@ __fp16\";
454 case 3: /* memory from ARM register */
455 return \"strh\\t%1, %0\\t%@ __fp16\";
456 case 4: /* S register from S register */
457 return \"vmov.f32\\t%0, %1\";
458 case 5: /* ARM register from ARM register */
459 return \"mov\\t%0, %1\\t%@ __fp16\";
460 case 6: /* S register from ARM register */
461 return \"vmov\\t%0, %1\";
462 case 7: /* ARM register from S register */
463 return \"vmov\\t%0, %1\";
464 case 8: /* ARM register from constant */
465 {
466 long bits;
467 rtx ops[4];
468
469 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
470 HFmode);
471 ops[0] = operands[0];
472 ops[1] = GEN_INT (bits);
473 ops[2] = GEN_INT (bits & 0xff00);
474 ops[3] = GEN_INT (bits & 0x00ff);
475
476 if (arm_arch_thumb2)
477 output_asm_insn (\"movw\\t%0, %1\", ops);
478 else
479 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
480 return \"\";
481 }
482 default:
483 gcc_unreachable ();
484 }
485 "
486 [(set_attr "conds" "unconditional")
487 (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\
488 load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
489 (set_attr "length" "4,4,4,4,4,4,4,4,8")]
490 )
491
492 ;; FP16 without element load/store instructions.
493 (define_insn "*movhf_vfp"
494 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
495 (match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))]
496 "TARGET_32BIT
497 && TARGET_HARD_FLOAT
498 && !TARGET_NEON_FP16
499 && !TARGET_VFP_FP16INST
500 && ( s_register_operand (operands[0], HFmode)
501 || s_register_operand (operands[1], HFmode))"
502 "*
503 switch (which_alternative)
504 {
505 case 0: /* ARM register from memory */
506 return \"ldrh\\t%0, %1\\t%@ __fp16\";
507 case 1: /* memory from ARM register */
508 return \"strh\\t%1, %0\\t%@ __fp16\";
509 case 2: /* S register from S register */
510 return \"vmov.f32\\t%0, %1\";
511 case 3: /* ARM register from ARM register */
512 return \"mov\\t%0, %1\\t%@ __fp16\";
513 case 4: /* S register from ARM register */
514 return \"vmov\\t%0, %1\";
515 case 5: /* ARM register from S register */
516 return \"vmov\\t%0, %1\";
517 case 6: /* ARM register from constant */
518 {
519 long bits;
520 rtx ops[4];
521
522 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
523 HFmode);
524 ops[0] = operands[0];
525 ops[1] = GEN_INT (bits);
526 ops[2] = GEN_INT (bits & 0xff00);
527 ops[3] = GEN_INT (bits & 0x00ff);
528
529 if (arm_arch_thumb2)
530 output_asm_insn (\"movw\\t%0, %1\", ops);
531 else
532 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
533 return \"\";
534 }
535 default:
536 gcc_unreachable ();
537 }
538 "
539 [(set_attr "conds" "unconditional")
540 (set_attr "type" "load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple")
541 (set_attr "length" "4,4,4,4,4,4,8")]
542 )
543
544
545 ;; SFmode moves
546 ;; Disparage the w<->r cases because reloading an invalid address is
547 ;; preferable to loading the value via integer registers.
548
549 (define_insn "*movsf_vfp"
550 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t ,Uv,r ,m,t,r")
551 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
552 "TARGET_ARM && TARGET_HARD_FLOAT
553 && ( s_register_operand (operands[0], SFmode)
554 || s_register_operand (operands[1], SFmode))"
555 "*
556 switch (which_alternative)
557 {
558 case 0:
559 return \"vmov%?\\t%0, %1\";
560 case 1:
561 return \"vmov%?\\t%0, %1\";
562 case 2:
563 return \"vmov%?.f32\\t%0, %1\";
564 case 3: case 4:
565 return output_move_vfp (operands);
566 case 5:
567 return \"ldr%?\\t%0, %1\\t%@ float\";
568 case 6:
569 return \"str%?\\t%1, %0\\t%@ float\";
570 case 7:
571 return \"vmov%?.f32\\t%0, %1\";
572 case 8:
573 return \"mov%?\\t%0, %1\\t%@ float\";
574 default:
575 gcc_unreachable ();
576 }
577 "
578 [(set_attr "predicable" "yes")
579 (set_attr "type"
580 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
581 (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
582 (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
583 )
584
585 (define_insn "*thumb2_movsf_vfp"
586 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t ,Uv,r ,m,t,r")
587 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
588 "TARGET_THUMB2 && TARGET_HARD_FLOAT
589 && ( s_register_operand (operands[0], SFmode)
590 || s_register_operand (operands[1], SFmode))"
591 "*
592 switch (which_alternative)
593 {
594 case 0:
595 return \"vmov%?\\t%0, %1\";
596 case 1:
597 return \"vmov%?\\t%0, %1\";
598 case 2:
599 return \"vmov%?.f32\\t%0, %1\";
600 case 3: case 4:
601 return output_move_vfp (operands);
602 case 5:
603 return \"ldr%?\\t%0, %1\\t%@ float\";
604 case 6:
605 return \"str%?\\t%1, %0\\t%@ float\";
606 case 7:
607 return \"vmov%?.f32\\t%0, %1\";
608 case 8:
609 return \"mov%?\\t%0, %1\\t%@ float\";
610 default:
611 gcc_unreachable ();
612 }
613 "
614 [(set_attr "predicable" "yes")
615 (set_attr "predicable_short_it" "no")
616 (set_attr "type"
617 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg")
618 (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*")
619 (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
620 )
621
622 ;; DFmode moves
623
624 (define_insn "*movdf_vfp"
625 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r, m,w,r")
626 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,G,UvF,w ,mF,r,w,r"))]
627 "TARGET_ARM && TARGET_HARD_FLOAT
628 && ( register_operand (operands[0], DFmode)
629 || register_operand (operands[1], DFmode))"
630 "*
631 {
632 switch (which_alternative)
633 {
634 case 0:
635 return \"vmov%?\\t%P0, %Q1, %R1\";
636 case 1:
637 return \"vmov%?\\t%Q0, %R0, %P1\";
638 case 2:
639 gcc_assert (TARGET_VFP_DOUBLE);
640 return \"vmov%?.f64\\t%P0, %1\";
641 case 3:
642 gcc_assert (TARGET_VFP_DOUBLE);
643 return \"vmov.i64\\t%P0, #0\\t%@ float\";
644 case 4: case 5:
645 return output_move_vfp (operands);
646 case 6: case 7:
647 return output_move_double (operands, true, NULL);
648 case 8:
649 if (TARGET_VFP_SINGLE)
650 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
651 else
652 return \"vmov%?.f64\\t%P0, %P1\";
653 case 9:
654 return \"#\";
655 default:
656 gcc_unreachable ();
657 }
658 }
659 "
660 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,f_stored,\
661 load_8,store_8,ffarithd,multiple")
662 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
663 (eq_attr "alternative" "8")
664 (if_then_else
665 (match_test "TARGET_VFP_SINGLE")
666 (const_int 8)
667 (const_int 4))]
668 (const_int 4)))
669 (set_attr "predicable" "yes,yes,yes,no,yes,yes,yes,yes,yes,yes")
670 (set_attr "pool_range" "*,*,*,*,1020,*,1020,*,*,*")
671 (set_attr "neg_pool_range" "*,*,*,*,1004,*,1004,*,*,*")
672 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
673 )
674
675 (define_insn "*thumb2_movdf_vfp"
676 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r ,m,w,r")
677 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,G,UvF,w, mF,r, w,r"))]
678 "TARGET_THUMB2 && TARGET_HARD_FLOAT
679 && ( register_operand (operands[0], DFmode)
680 || register_operand (operands[1], DFmode))"
681 "*
682 {
683 switch (which_alternative)
684 {
685 case 0:
686 return \"vmov%?\\t%P0, %Q1, %R1\";
687 case 1:
688 return \"vmov%?\\t%Q0, %R0, %P1\";
689 case 2:
690 gcc_assert (TARGET_VFP_DOUBLE);
691 return \"vmov%?.f64\\t%P0, %1\";
692 case 3:
693 gcc_assert (TARGET_VFP_DOUBLE);
694 return \"vmov.i64\\t%P0, #0\\t%@ float\";
695 case 4: case 5:
696 return output_move_vfp (operands);
697 case 6: case 7: case 9:
698 return output_move_double (operands, true, NULL);
699 case 8:
700 if (TARGET_VFP_SINGLE)
701 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
702 else
703 return \"vmov%?.f64\\t%P0, %P1\";
704 default:
705 abort ();
706 }
707 }
708 "
709 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,\
710 f_stored,load_8,store_8,ffarithd,multiple")
711 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
712 (eq_attr "alternative" "8")
713 (if_then_else
714 (match_test "TARGET_VFP_SINGLE")
715 (const_int 8)
716 (const_int 4))]
717 (const_int 4)))
718 (set_attr "pool_range" "*,*,*,*,1018,*,4094,*,*,*")
719 (set_attr "neg_pool_range" "*,*,*,*,1008,*,0,*,*,*")
720 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")]
721 )
722
723
724 ;; Conditional move patterns
725
726 (define_insn "*movsfcc_vfp"
727 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
728 (if_then_else:SF
729 (match_operator 3 "arm_comparison_operator"
730 [(match_operand 4 "cc_register" "") (const_int 0)])
731 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
732 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
733 "TARGET_ARM && TARGET_HARD_FLOAT"
734 "@
735 vmov%D3.f32\\t%0, %2
736 vmov%d3.f32\\t%0, %1
737 vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
738 vmov%D3\\t%0, %2
739 vmov%d3\\t%0, %1
740 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
741 vmov%D3\\t%0, %2
742 vmov%d3\\t%0, %1
743 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
744 [(set_attr "conds" "use")
745 (set_attr "length" "4,4,8,4,4,8,4,4,8")
746 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
747 )
748
749 (define_insn "*thumb2_movsfcc_vfp"
750 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
751 (if_then_else:SF
752 (match_operator 3 "arm_comparison_operator"
753 [(match_operand 4 "cc_register" "") (const_int 0)])
754 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
755 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
756 "TARGET_THUMB2 && TARGET_HARD_FLOAT && !arm_restrict_it"
757 "@
758 it\\t%D3\;vmov%D3.f32\\t%0, %2
759 it\\t%d3\;vmov%d3.f32\\t%0, %1
760 ite\\t%D3\;vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1
761 it\\t%D3\;vmov%D3\\t%0, %2
762 it\\t%d3\;vmov%d3\\t%0, %1
763 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1
764 it\\t%D3\;vmov%D3\\t%0, %2
765 it\\t%d3\;vmov%d3\\t%0, %1
766 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1"
767 [(set_attr "conds" "use")
768 (set_attr "length" "6,6,10,6,6,10,6,6,10")
769 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
770 )
771
772 (define_insn "*movdfcc_vfp"
773 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
774 (if_then_else:DF
775 (match_operator 3 "arm_comparison_operator"
776 [(match_operand 4 "cc_register" "") (const_int 0)])
777 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
778 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
779 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
780 "@
781 vmov%D3.f64\\t%P0, %P2
782 vmov%d3.f64\\t%P0, %P1
783 vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
784 vmov%D3\\t%P0, %Q2, %R2
785 vmov%d3\\t%P0, %Q1, %R1
786 vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
787 vmov%D3\\t%Q0, %R0, %P2
788 vmov%d3\\t%Q0, %R0, %P1
789 vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
790 [(set_attr "conds" "use")
791 (set_attr "length" "4,4,8,4,4,8,4,4,8")
792 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcr,f_mrrc,f_mrrc,f_mrrc")]
793 )
794
795 (define_insn "*thumb2_movdfcc_vfp"
796 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
797 (if_then_else:DF
798 (match_operator 3 "arm_comparison_operator"
799 [(match_operand 4 "cc_register" "") (const_int 0)])
800 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
801 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
802 "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && !arm_restrict_it"
803 "@
804 it\\t%D3\;vmov%D3.f64\\t%P0, %P2
805 it\\t%d3\;vmov%d3.f64\\t%P0, %P1
806 ite\\t%D3\;vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1
807 it\t%D3\;vmov%D3\\t%P0, %Q2, %R2
808 it\t%d3\;vmov%d3\\t%P0, %Q1, %R1
809 ite\\t%D3\;vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1
810 it\t%D3\;vmov%D3\\t%Q0, %R0, %P2
811 it\t%d3\;vmov%d3\\t%Q0, %R0, %P1
812 ite\\t%D3\;vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1"
813 [(set_attr "conds" "use")
814 (set_attr "length" "6,6,10,6,6,10,6,6,10")
815 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcrr,f_mrrc,f_mrrc,f_mrrc")]
816 )
817
818
819 ;; Sign manipulation functions
820
821 (define_insn "*abssf2_vfp"
822 [(set (match_operand:SF 0 "s_register_operand" "=t")
823 (abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
824 "TARGET_32BIT && TARGET_HARD_FLOAT"
825 "vabs%?.f32\\t%0, %1"
826 [(set_attr "predicable" "yes")
827 (set_attr "predicable_short_it" "no")
828 (set_attr "type" "ffariths")]
829 )
830
831 (define_insn "*absdf2_vfp"
832 [(set (match_operand:DF 0 "s_register_operand" "=w")
833 (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
834 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
835 "vabs%?.f64\\t%P0, %P1"
836 [(set_attr "predicable" "yes")
837 (set_attr "predicable_short_it" "no")
838 (set_attr "type" "ffarithd")]
839 )
840
841 (define_insn "*negsf2_vfp"
842 [(set (match_operand:SF 0 "s_register_operand" "=t,?r")
843 (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))]
844 "TARGET_32BIT && TARGET_HARD_FLOAT"
845 "@
846 vneg%?.f32\\t%0, %1
847 eor%?\\t%0, %1, #-2147483648"
848 [(set_attr "predicable" "yes")
849 (set_attr "predicable_short_it" "no")
850 (set_attr "type" "ffariths")]
851 )
852
853 (define_insn_and_split "*negdf2_vfp"
854 [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r")
855 (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
856 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
857 "@
858 vneg%?.f64\\t%P0, %P1
859 #
860 #"
861 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
862 && arm_general_register_operand (operands[0], DFmode)"
863 [(set (match_dup 0) (match_dup 1))]
864 "
865 if (REGNO (operands[0]) == REGNO (operands[1]))
866 {
867 operands[0] = gen_highpart (SImode, operands[0]);
868 operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
869 }
870 else
871 {
872 rtx in_hi, in_lo, out_hi, out_lo;
873
874 in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
875 GEN_INT (0x80000000));
876 in_lo = gen_lowpart (SImode, operands[1]);
877 out_hi = gen_highpart (SImode, operands[0]);
878 out_lo = gen_lowpart (SImode, operands[0]);
879
880 if (REGNO (in_lo) == REGNO (out_hi))
881 {
882 emit_insn (gen_rtx_SET (out_lo, in_lo));
883 operands[0] = out_hi;
884 operands[1] = in_hi;
885 }
886 else
887 {
888 emit_insn (gen_rtx_SET (out_hi, in_hi));
889 operands[0] = out_lo;
890 operands[1] = in_lo;
891 }
892 }
893 "
894 [(set_attr "predicable" "yes")
895 (set_attr "predicable_short_it" "no")
896 (set_attr "length" "4,4,8")
897 (set_attr "type" "ffarithd")]
898 )
899
900 ;; ABS and NEG for FP16.
901 (define_insn "<absneg_str>hf2"
902 [(set (match_operand:HF 0 "s_register_operand" "=w")
903 (ABSNEG:HF (match_operand:HF 1 "s_register_operand" "w")))]
904 "TARGET_VFP_FP16INST"
905 "v<absneg_str>.f16\t%0, %1"
906 [(set_attr "conds" "unconditional")
907 (set_attr "type" "ffariths")]
908 )
909
910 (define_expand "neon_vabshf"
911 [(set
912 (match_operand:HF 0 "s_register_operand")
913 (abs:HF (match_operand:HF 1 "s_register_operand")))]
914 "TARGET_VFP_FP16INST"
915 {
916 emit_insn (gen_abshf2 (operands[0], operands[1]));
917 DONE;
918 })
919
920 ;; VRND for FP16.
921 (define_insn "neon_v<fp16_rnd_str>hf"
922 [(set (match_operand:HF 0 "s_register_operand" "=w")
923 (unspec:HF
924 [(match_operand:HF 1 "s_register_operand" "w")]
925 FP16_RND))]
926 "TARGET_VFP_FP16INST"
927 "<fp16_rnd_insn>.f16\t%0, %1"
928 [(set_attr "conds" "unconditional")
929 (set_attr "type" "neon_fp_round_s")]
930 )
931
932 (define_insn "neon_vrndihf"
933 [(set (match_operand:HF 0 "s_register_operand" "=w")
934 (unspec:HF
935 [(match_operand:HF 1 "s_register_operand" "w")]
936 UNSPEC_VRNDI))]
937 "TARGET_VFP_FP16INST"
938 "vrintr.f16\t%0, %1"
939 [(set_attr "conds" "unconditional")
940 (set_attr "type" "neon_fp_round_s")]
941 )
942
943 ;; Arithmetic insns
944
945 (define_insn "addhf3"
946 [(set
947 (match_operand:HF 0 "s_register_operand" "=w")
948 (plus:HF
949 (match_operand:HF 1 "s_register_operand" "w")
950 (match_operand:HF 2 "s_register_operand" "w")))]
951 "TARGET_VFP_FP16INST"
952 "vadd.f16\t%0, %1, %2"
953 [(set_attr "conds" "unconditional")
954 (set_attr "type" "fadds")]
955 )
956
957 (define_insn "*addsf3_vfp"
958 [(set (match_operand:SF 0 "s_register_operand" "=t")
959 (plus:SF (match_operand:SF 1 "s_register_operand" "t")
960 (match_operand:SF 2 "s_register_operand" "t")))]
961 "TARGET_32BIT && TARGET_HARD_FLOAT"
962 "vadd%?.f32\\t%0, %1, %2"
963 [(set_attr "predicable" "yes")
964 (set_attr "predicable_short_it" "no")
965 (set_attr "type" "fadds")]
966 )
967
968 (define_insn "*adddf3_vfp"
969 [(set (match_operand:DF 0 "s_register_operand" "=w")
970 (plus:DF (match_operand:DF 1 "s_register_operand" "w")
971 (match_operand:DF 2 "s_register_operand" "w")))]
972 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
973 "vadd%?.f64\\t%P0, %P1, %P2"
974 [(set_attr "predicable" "yes")
975 (set_attr "predicable_short_it" "no")
976 (set_attr "type" "faddd")]
977 )
978
979 (define_insn "subhf3"
980 [(set
981 (match_operand:HF 0 "s_register_operand" "=w")
982 (minus:HF
983 (match_operand:HF 1 "s_register_operand" "w")
984 (match_operand:HF 2 "s_register_operand" "w")))]
985 "TARGET_VFP_FP16INST"
986 "vsub.f16\t%0, %1, %2"
987 [(set_attr "conds" "unconditional")
988 (set_attr "type" "fadds")]
989 )
990
991 (define_insn "*subsf3_vfp"
992 [(set (match_operand:SF 0 "s_register_operand" "=t")
993 (minus:SF (match_operand:SF 1 "s_register_operand" "t")
994 (match_operand:SF 2 "s_register_operand" "t")))]
995 "TARGET_32BIT && TARGET_HARD_FLOAT"
996 "vsub%?.f32\\t%0, %1, %2"
997 [(set_attr "predicable" "yes")
998 (set_attr "predicable_short_it" "no")
999 (set_attr "type" "fadds")]
1000 )
1001
1002 (define_insn "*subdf3_vfp"
1003 [(set (match_operand:DF 0 "s_register_operand" "=w")
1004 (minus:DF (match_operand:DF 1 "s_register_operand" "w")
1005 (match_operand:DF 2 "s_register_operand" "w")))]
1006 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1007 "vsub%?.f64\\t%P0, %P1, %P2"
1008 [(set_attr "predicable" "yes")
1009 (set_attr "predicable_short_it" "no")
1010 (set_attr "type" "faddd")]
1011 )
1012
1013
1014 ;; Division insns
1015
1016 ;; FP16 Division.
1017 (define_insn "divhf3"
1018 [(set
1019 (match_operand:HF 0 "s_register_operand" "=w")
1020 (div:HF
1021 (match_operand:HF 1 "s_register_operand" "w")
1022 (match_operand:HF 2 "s_register_operand" "w")))]
1023 "TARGET_VFP_FP16INST"
1024 "vdiv.f16\t%0, %1, %2"
1025 [(set_attr "conds" "unconditional")
1026 (set_attr "type" "fdivs")]
1027 )
1028
1029 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1030 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1031 ; earlier.
1032 (define_insn "*divsf3_vfp"
1033 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1034 (div:SF (match_operand:SF 1 "s_register_operand" "t,t")
1035 (match_operand:SF 2 "s_register_operand" "t,t")))]
1036 "TARGET_32BIT && TARGET_HARD_FLOAT"
1037 "vdiv%?.f32\\t%0, %1, %2"
1038 [(set_attr "predicable" "yes")
1039 (set_attr "predicable_short_it" "no")
1040 (set_attr "arch" "*,armv6_or_vfpv3")
1041 (set_attr "type" "fdivs")]
1042 )
1043
1044 (define_insn "*divdf3_vfp"
1045 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1046 (div:DF (match_operand:DF 1 "s_register_operand" "w,w")
1047 (match_operand:DF 2 "s_register_operand" "w,w")))]
1048 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1049 "vdiv%?.f64\\t%P0, %P1, %P2"
1050 [(set_attr "predicable" "yes")
1051 (set_attr "predicable_short_it" "no")
1052 (set_attr "arch" "*,armv6_or_vfpv3")
1053 (set_attr "type" "fdivd")]
1054 )
1055
1056
1057 ;; Multiplication insns
1058
1059 (define_insn "mulhf3"
1060 [(set
1061 (match_operand:HF 0 "s_register_operand" "=w")
1062 (mult:HF (match_operand:HF 1 "s_register_operand" "w")
1063 (match_operand:HF 2 "s_register_operand" "w")))]
1064 "TARGET_VFP_FP16INST"
1065 "vmul.f16\t%0, %1, %2"
1066 [(set_attr "conds" "unconditional")
1067 (set_attr "type" "fmuls")]
1068 )
1069
1070 (define_insn "*mulsf3_vfp"
1071 [(set (match_operand:SF 0 "s_register_operand" "=t")
1072 (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1073 (match_operand:SF 2 "s_register_operand" "t")))]
1074 "TARGET_32BIT && TARGET_HARD_FLOAT"
1075 "vmul%?.f32\\t%0, %1, %2"
1076 [(set_attr "predicable" "yes")
1077 (set_attr "predicable_short_it" "no")
1078 (set_attr "type" "fmuls")]
1079 )
1080
1081 (define_insn "*muldf3_vfp"
1082 [(set (match_operand:DF 0 "s_register_operand" "=w")
1083 (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1084 (match_operand:DF 2 "s_register_operand" "w")))]
1085 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1086 "vmul%?.f64\\t%P0, %P1, %P2"
1087 [(set_attr "predicable" "yes")
1088 (set_attr "predicable_short_it" "no")
1089 (set_attr "type" "fmuld")]
1090 )
1091
1092 (define_insn "*mulsf3neghf_vfp"
1093 [(set (match_operand:HF 0 "s_register_operand" "=t")
1094 (mult:HF (neg:HF (match_operand:HF 1 "s_register_operand" "t"))
1095 (match_operand:HF 2 "s_register_operand" "t")))]
1096 "TARGET_VFP_FP16INST && !flag_rounding_math"
1097 "vnmul.f16\\t%0, %1, %2"
1098 [(set_attr "conds" "unconditional")
1099 (set_attr "type" "fmuls")]
1100 )
1101
1102 (define_insn "*negmulhf3_vfp"
1103 [(set (match_operand:HF 0 "s_register_operand" "=t")
1104 (neg:HF (mult:HF (match_operand:HF 1 "s_register_operand" "t")
1105 (match_operand:HF 2 "s_register_operand" "t"))))]
1106 "TARGET_VFP_FP16INST"
1107 "vnmul.f16\\t%0, %1, %2"
1108 [(set_attr "conds" "unconditional")
1109 (set_attr "type" "fmuls")]
1110 )
1111
1112 (define_insn "*mulsf3negsf_vfp"
1113 [(set (match_operand:SF 0 "s_register_operand" "=t")
1114 (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
1115 (match_operand:SF 2 "s_register_operand" "t")))]
1116 "TARGET_32BIT && TARGET_HARD_FLOAT && !flag_rounding_math"
1117 "vnmul%?.f32\\t%0, %1, %2"
1118 [(set_attr "predicable" "yes")
1119 (set_attr "predicable_short_it" "no")
1120 (set_attr "type" "fmuls")]
1121 )
1122
1123 (define_insn "*negmulsf3_vfp"
1124 [(set (match_operand:SF 0 "s_register_operand" "=t")
1125 (neg:SF (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1126 (match_operand:SF 2 "s_register_operand" "t"))))]
1127 "TARGET_32BIT && TARGET_HARD_FLOAT"
1128 "vnmul%?.f32\\t%0, %1, %2"
1129 [(set_attr "predicable" "yes")
1130 (set_attr "predicable_short_it" "no")
1131 (set_attr "type" "fmuls")]
1132 )
1133
1134 (define_insn "*muldf3negdf_vfp"
1135 [(set (match_operand:DF 0 "s_register_operand" "=w")
1136 (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
1137 (match_operand:DF 2 "s_register_operand" "w")))]
1138 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
1139 && !flag_rounding_math"
1140 "vnmul%?.f64\\t%P0, %P1, %P2"
1141 [(set_attr "predicable" "yes")
1142 (set_attr "predicable_short_it" "no")
1143 (set_attr "type" "fmuld")]
1144 )
1145
1146 (define_insn "*negmuldf3_vfp"
1147 [(set (match_operand:DF 0 "s_register_operand" "=w")
1148 (neg:DF (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1149 (match_operand:DF 2 "s_register_operand" "w"))))]
1150 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1151 "vnmul%?.f64\\t%P0, %P1, %P2"
1152 [(set_attr "predicable" "yes")
1153 (set_attr "predicable_short_it" "no")
1154 (set_attr "type" "fmuld")]
1155 )
1156
1157
1158 ;; Multiply-accumulate insns
1159
1160 ;; 0 = 1 * 2 + 0
1161 (define_insn "*mulsf3addhf_vfp"
1162 [(set (match_operand:HF 0 "s_register_operand" "=t")
1163 (plus:HF
1164 (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1165 (match_operand:HF 3 "s_register_operand" "t"))
1166 (match_operand:HF 1 "s_register_operand" "0")))]
1167 "TARGET_VFP_FP16INST"
1168 "vmla.f16\\t%0, %2, %3"
1169 [(set_attr "conds" "unconditional")
1170 (set_attr "type" "fmacs")]
1171 )
1172
1173 (define_insn "*mulsf3addsf_vfp"
1174 [(set (match_operand:SF 0 "s_register_operand" "=t")
1175 (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1176 (match_operand:SF 3 "s_register_operand" "t"))
1177 (match_operand:SF 1 "s_register_operand" "0")))]
1178 "TARGET_32BIT && TARGET_HARD_FLOAT"
1179 "vmla%?.f32\\t%0, %2, %3"
1180 [(set_attr "predicable" "yes")
1181 (set_attr "predicable_short_it" "no")
1182 (set_attr "type" "fmacs")]
1183 )
1184
1185 (define_insn "*muldf3adddf_vfp"
1186 [(set (match_operand:DF 0 "s_register_operand" "=w")
1187 (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1188 (match_operand:DF 3 "s_register_operand" "w"))
1189 (match_operand:DF 1 "s_register_operand" "0")))]
1190 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1191 "vmla%?.f64\\t%P0, %P2, %P3"
1192 [(set_attr "predicable" "yes")
1193 (set_attr "predicable_short_it" "no")
1194 (set_attr "type" "fmacd")]
1195 )
1196
1197 ;; 0 = 1 * 2 - 0
1198 (define_insn "*mulhf3subhf_vfp"
1199 [(set (match_operand:HF 0 "s_register_operand" "=t")
1200 (minus:HF (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1201 (match_operand:HF 3 "s_register_operand" "t"))
1202 (match_operand:HF 1 "s_register_operand" "0")))]
1203 "TARGET_VFP_FP16INST"
1204 "vnmls.f16\\t%0, %2, %3"
1205 [(set_attr "conds" "unconditional")
1206 (set_attr "type" "fmacs")]
1207 )
1208
1209 (define_insn "*mulsf3subsf_vfp"
1210 [(set (match_operand:SF 0 "s_register_operand" "=t")
1211 (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1212 (match_operand:SF 3 "s_register_operand" "t"))
1213 (match_operand:SF 1 "s_register_operand" "0")))]
1214 "TARGET_32BIT && TARGET_HARD_FLOAT"
1215 "vnmls%?.f32\\t%0, %2, %3"
1216 [(set_attr "predicable" "yes")
1217 (set_attr "predicable_short_it" "no")
1218 (set_attr "type" "fmacs")]
1219 )
1220
1221 (define_insn "*muldf3subdf_vfp"
1222 [(set (match_operand:DF 0 "s_register_operand" "=w")
1223 (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1224 (match_operand:DF 3 "s_register_operand" "w"))
1225 (match_operand:DF 1 "s_register_operand" "0")))]
1226 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1227 "vnmls%?.f64\\t%P0, %P2, %P3"
1228 [(set_attr "predicable" "yes")
1229 (set_attr "predicable_short_it" "no")
1230 (set_attr "type" "fmacd")]
1231 )
1232
1233 ;; 0 = -(1 * 2) + 0
1234 (define_insn "*mulhf3neghfaddhf_vfp"
1235 [(set (match_operand:HF 0 "s_register_operand" "=t")
1236 (minus:HF (match_operand:HF 1 "s_register_operand" "0")
1237 (mult:HF (match_operand:HF 2 "s_register_operand" "t")
1238 (match_operand:HF 3 "s_register_operand" "t"))))]
1239 "TARGET_VFP_FP16INST"
1240 "vmls.f16\\t%0, %2, %3"
1241 [(set_attr "conds" "unconditional")
1242 (set_attr "type" "fmacs")]
1243 )
1244
1245 (define_insn "*mulsf3negsfaddsf_vfp"
1246 [(set (match_operand:SF 0 "s_register_operand" "=t")
1247 (minus:SF (match_operand:SF 1 "s_register_operand" "0")
1248 (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1249 (match_operand:SF 3 "s_register_operand" "t"))))]
1250 "TARGET_32BIT && TARGET_HARD_FLOAT"
1251 "vmls%?.f32\\t%0, %2, %3"
1252 [(set_attr "predicable" "yes")
1253 (set_attr "predicable_short_it" "no")
1254 (set_attr "type" "fmacs")]
1255 )
1256
1257 (define_insn "*fmuldf3negdfadddf_vfp"
1258 [(set (match_operand:DF 0 "s_register_operand" "=w")
1259 (minus:DF (match_operand:DF 1 "s_register_operand" "0")
1260 (mult:DF (match_operand:DF 2 "s_register_operand" "w")
1261 (match_operand:DF 3 "s_register_operand" "w"))))]
1262 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1263 "vmls%?.f64\\t%P0, %P2, %P3"
1264 [(set_attr "predicable" "yes")
1265 (set_attr "predicable_short_it" "no")
1266 (set_attr "type" "fmacd")]
1267 )
1268
1269
1270 ;; 0 = -(1 * 2) - 0
1271 (define_insn "*mulhf3neghfsubhf_vfp"
1272 [(set (match_operand:HF 0 "s_register_operand" "=t")
1273 (minus:HF (mult:HF
1274 (neg:HF (match_operand:HF 2 "s_register_operand" "t"))
1275 (match_operand:HF 3 "s_register_operand" "t"))
1276 (match_operand:HF 1 "s_register_operand" "0")))]
1277 "TARGET_VFP_FP16INST"
1278 "vnmla.f16\\t%0, %2, %3"
1279 [(set_attr "conds" "unconditional")
1280 (set_attr "type" "fmacs")]
1281 )
1282
1283 (define_insn "*mulsf3negsfsubsf_vfp"
1284 [(set (match_operand:SF 0 "s_register_operand" "=t")
1285 (minus:SF (mult:SF
1286 (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
1287 (match_operand:SF 3 "s_register_operand" "t"))
1288 (match_operand:SF 1 "s_register_operand" "0")))]
1289 "TARGET_32BIT && TARGET_HARD_FLOAT"
1290 "vnmla%?.f32\\t%0, %2, %3"
1291 [(set_attr "predicable" "yes")
1292 (set_attr "predicable_short_it" "no")
1293 (set_attr "type" "fmacs")]
1294 )
1295
1296 (define_insn "*muldf3negdfsubdf_vfp"
1297 [(set (match_operand:DF 0 "s_register_operand" "=w")
1298 (minus:DF (mult:DF
1299 (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
1300 (match_operand:DF 3 "s_register_operand" "w"))
1301 (match_operand:DF 1 "s_register_operand" "0")))]
1302 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1303 "vnmla%?.f64\\t%P0, %P2, %P3"
1304 [(set_attr "predicable" "yes")
1305 (set_attr "predicable_short_it" "no")
1306 (set_attr "type" "fmacd")]
1307 )
1308
1309 ;; Fused-multiply-accumulate
1310
1311 (define_insn "fmahf4"
1312 [(set (match_operand:HF 0 "register_operand" "=w")
1313 (fma:HF
1314 (match_operand:HF 1 "register_operand" "w")
1315 (match_operand:HF 2 "register_operand" "w")
1316 (match_operand:HF 3 "register_operand" "0")))]
1317 "TARGET_VFP_FP16INST"
1318 "vfma.f16\\t%0, %1, %2"
1319 [(set_attr "conds" "unconditional")
1320 (set_attr "type" "ffmas")]
1321 )
1322
1323 (define_expand "neon_vfmahf"
1324 [(match_operand:HF 0 "s_register_operand")
1325 (match_operand:HF 1 "s_register_operand")
1326 (match_operand:HF 2 "s_register_operand")
1327 (match_operand:HF 3 "s_register_operand")]
1328 "TARGET_VFP_FP16INST"
1329 {
1330 emit_insn (gen_fmahf4 (operands[0], operands[2], operands[3],
1331 operands[1]));
1332 DONE;
1333 })
1334
1335 (define_insn "fma<SDF:mode>4"
1336 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1337 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1338 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1339 (match_operand:SDF 3 "register_operand" "0")))]
1340 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1341 "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1342 [(set_attr "predicable" "yes")
1343 (set_attr "predicable_short_it" "no")
1344 (set_attr "type" "ffma<vfp_type>")]
1345 )
1346
1347 (define_insn "fmsubhf4_fp16"
1348 [(set (match_operand:HF 0 "register_operand" "=w")
1349 (fma:HF
1350 (neg:HF (match_operand:HF 1 "register_operand" "w"))
1351 (match_operand:HF 2 "register_operand" "w")
1352 (match_operand:HF 3 "register_operand" "0")))]
1353 "TARGET_VFP_FP16INST"
1354 "vfms.f16\\t%0, %1, %2"
1355 [(set_attr "conds" "unconditional")
1356 (set_attr "type" "ffmas")]
1357 )
1358
1359 (define_expand "neon_vfmshf"
1360 [(match_operand:HF 0 "s_register_operand")
1361 (match_operand:HF 1 "s_register_operand")
1362 (match_operand:HF 2 "s_register_operand")
1363 (match_operand:HF 3 "s_register_operand")]
1364 "TARGET_VFP_FP16INST"
1365 {
1366 emit_insn (gen_fmsubhf4_fp16 (operands[0], operands[2], operands[3],
1367 operands[1]));
1368 DONE;
1369 })
1370
1371 (define_insn "*fmsub<SDF:mode>4"
1372 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1373 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1374 "<F_constraint>"))
1375 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1376 (match_operand:SDF 3 "register_operand" "0")))]
1377 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1378 "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1379 [(set_attr "predicable" "yes")
1380 (set_attr "predicable_short_it" "no")
1381 (set_attr "type" "ffma<vfp_type>")]
1382 )
1383
1384 (define_insn "*fnmsubhf4"
1385 [(set (match_operand:HF 0 "register_operand" "=w")
1386 (fma:HF (match_operand:HF 1 "register_operand" "w")
1387 (match_operand:HF 2 "register_operand" "w")
1388 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1389 "TARGET_VFP_FP16INST"
1390 "vfnms.f16\\t%0, %1, %2"
1391 [(set_attr "conds" "unconditional")
1392 (set_attr "type" "ffmas")]
1393 )
1394
1395 (define_insn "*fnmsub<SDF:mode>4"
1396 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1397 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1398 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1399 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1400 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1401 "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1402 [(set_attr "predicable" "yes")
1403 (set_attr "predicable_short_it" "no")
1404 (set_attr "type" "ffma<vfp_type>")]
1405 )
1406
1407 (define_insn "*fnmaddhf4"
1408 [(set (match_operand:HF 0 "register_operand" "=w")
1409 (fma:HF (neg:HF (match_operand:HF 1 "register_operand" "w"))
1410 (match_operand:HF 2 "register_operand" "w")
1411 (neg:HF (match_operand:HF 3 "register_operand" "0"))))]
1412 "TARGET_VFP_FP16INST"
1413 "vfnma.f16\\t%0, %1, %2"
1414 [(set_attr "conds" "unconditional")
1415 (set_attr "type" "ffmas")]
1416 )
1417
1418 (define_insn "*fnmadd<SDF:mode>4"
1419 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1420 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand"
1421 "<F_constraint>"))
1422 (match_operand:SDF 2 "register_operand" "<F_constraint>")
1423 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))]
1424 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA"
1425 "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1426 [(set_attr "predicable" "yes")
1427 (set_attr "predicable_short_it" "no")
1428 (set_attr "type" "ffma<vfp_type>")]
1429 )
1430
1431
1432 ;; Conversion routines
1433
1434 (define_insn "*extendsfdf2_vfp"
1435 [(set (match_operand:DF 0 "s_register_operand" "=w")
1436 (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
1437 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1438 "vcvt%?.f64.f32\\t%P0, %1"
1439 [(set_attr "predicable" "yes")
1440 (set_attr "predicable_short_it" "no")
1441 (set_attr "type" "f_cvt")]
1442 )
1443
1444 (define_insn "*truncdfsf2_vfp"
1445 [(set (match_operand:SF 0 "s_register_operand" "=t")
1446 (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
1447 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1448 "vcvt%?.f32.f64\\t%0, %P1"
1449 [(set_attr "predicable" "yes")
1450 (set_attr "predicable_short_it" "no")
1451 (set_attr "type" "f_cvt")]
1452 )
1453
1454 (define_insn "extendhfsf2"
1455 [(set (match_operand:SF 0 "s_register_operand" "=t")
1456 (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))]
1457 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1458 "vcvtb%?.f32.f16\\t%0, %1"
1459 [(set_attr "predicable" "yes")
1460 (set_attr "predicable_short_it" "no")
1461 (set_attr "type" "f_cvt")]
1462 )
1463
1464 (define_insn "*truncdfhf2"
1465 [(set (match_operand:HF 0 "s_register_operand" "=t")
1466 (float_truncate:HF (match_operand:DF 1 "s_register_operand" "w")))]
1467 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1468 "vcvtb%?.f16.f64\\t%0, %P1"
1469 [(set_attr "predicable" "yes")
1470 (set_attr "predicable_short_it" "no")
1471 (set_attr "type" "f_cvt")]
1472 )
1473
1474 (define_insn "*extendhfdf2"
1475 [(set (match_operand:DF 0 "s_register_operand" "=w")
1476 (float_extend:DF (match_operand:HF 1 "s_register_operand" "t")))]
1477 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1478 "vcvtb%?.f64.f16\\t%P0, %1"
1479 [(set_attr "predicable" "yes")
1480 (set_attr "predicable_short_it" "no")
1481 (set_attr "type" "f_cvt")]
1482 )
1483
1484 (define_insn "truncsfhf2"
1485 [(set (match_operand:HF 0 "s_register_operand" "=t")
1486 (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
1487 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
1488 "vcvtb%?.f16.f32\\t%0, %1"
1489 [(set_attr "predicable" "yes")
1490 (set_attr "predicable_short_it" "no")
1491 (set_attr "type" "f_cvt")]
1492 )
1493
1494 (define_insn "*truncsisf2_vfp"
1495 [(set (match_operand:SI 0 "s_register_operand" "=t")
1496 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1497 "TARGET_32BIT && TARGET_HARD_FLOAT"
1498 "vcvt%?.s32.f32\\t%0, %1"
1499 [(set_attr "predicable" "yes")
1500 (set_attr "predicable_short_it" "no")
1501 (set_attr "type" "f_cvtf2i")]
1502 )
1503
1504 (define_insn "*truncsidf2_vfp"
1505 [(set (match_operand:SI 0 "s_register_operand" "=t")
1506 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
1507 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1508 "vcvt%?.s32.f64\\t%0, %P1"
1509 [(set_attr "predicable" "yes")
1510 (set_attr "predicable_short_it" "no")
1511 (set_attr "type" "f_cvtf2i")]
1512 )
1513
1514
1515 (define_insn "fixuns_truncsfsi2"
1516 [(set (match_operand:SI 0 "s_register_operand" "=t")
1517 (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
1518 "TARGET_32BIT && TARGET_HARD_FLOAT"
1519 "vcvt%?.u32.f32\\t%0, %1"
1520 [(set_attr "predicable" "yes")
1521 (set_attr "predicable_short_it" "no")
1522 (set_attr "type" "f_cvtf2i")]
1523 )
1524
1525 (define_insn "fixuns_truncdfsi2"
1526 [(set (match_operand:SI 0 "s_register_operand" "=t")
1527 (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
1528 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1529 "vcvt%?.u32.f64\\t%0, %P1"
1530 [(set_attr "predicable" "yes")
1531 (set_attr "predicable_short_it" "no")
1532 (set_attr "type" "f_cvtf2i")]
1533 )
1534
1535
1536 (define_insn "*floatsisf2_vfp"
1537 [(set (match_operand:SF 0 "s_register_operand" "=t")
1538 (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1539 "TARGET_32BIT && TARGET_HARD_FLOAT"
1540 "vcvt%?.f32.s32\\t%0, %1"
1541 [(set_attr "predicable" "yes")
1542 (set_attr "predicable_short_it" "no")
1543 (set_attr "type" "f_cvti2f")]
1544 )
1545
1546 (define_insn "*floatsidf2_vfp"
1547 [(set (match_operand:DF 0 "s_register_operand" "=w")
1548 (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1549 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1550 "vcvt%?.f64.s32\\t%P0, %1"
1551 [(set_attr "predicable" "yes")
1552 (set_attr "predicable_short_it" "no")
1553 (set_attr "type" "f_cvti2f")]
1554 )
1555
1556
1557 (define_insn "floatunssisf2"
1558 [(set (match_operand:SF 0 "s_register_operand" "=t")
1559 (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
1560 "TARGET_32BIT && TARGET_HARD_FLOAT"
1561 "vcvt%?.f32.u32\\t%0, %1"
1562 [(set_attr "predicable" "yes")
1563 (set_attr "predicable_short_it" "no")
1564 (set_attr "type" "f_cvti2f")]
1565 )
1566
1567 (define_insn "floatunssidf2"
1568 [(set (match_operand:DF 0 "s_register_operand" "=w")
1569 (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
1570 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1571 "vcvt%?.f64.u32\\t%P0, %1"
1572 [(set_attr "predicable" "yes")
1573 (set_attr "predicable_short_it" "no")
1574 (set_attr "type" "f_cvti2f")]
1575 )
1576
1577
1578 ;; Sqrt insns.
1579
1580 (define_insn "neon_vsqrthf"
1581 [(set (match_operand:HF 0 "s_register_operand" "=w")
1582 (sqrt:HF (match_operand:HF 1 "s_register_operand" "w")))]
1583 "TARGET_VFP_FP16INST"
1584 "vsqrt.f16\t%0, %1"
1585 [(set_attr "conds" "unconditional")
1586 (set_attr "type" "fsqrts")]
1587 )
1588
1589 (define_insn "neon_vrsqrtshf"
1590 [(set
1591 (match_operand:HF 0 "s_register_operand" "=w")
1592 (unspec:HF [(match_operand:HF 1 "s_register_operand" "w")
1593 (match_operand:HF 2 "s_register_operand" "w")]
1594 UNSPEC_VRSQRTS))]
1595 "TARGET_VFP_FP16INST"
1596 "vrsqrts.f16\t%0, %1, %2"
1597 [(set_attr "conds" "unconditional")
1598 (set_attr "type" "fsqrts")]
1599 )
1600
1601 ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1602 ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1603 ; earlier.
1604 (define_insn "*sqrtsf2_vfp"
1605 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1606 (sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))]
1607 "TARGET_32BIT && TARGET_HARD_FLOAT"
1608 "vsqrt%?.f32\\t%0, %1"
1609 [(set_attr "predicable" "yes")
1610 (set_attr "predicable_short_it" "no")
1611 (set_attr "arch" "*,armv6_or_vfpv3")
1612 (set_attr "type" "fsqrts")]
1613 )
1614
1615 (define_insn "*sqrtdf2_vfp"
1616 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1617 (sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))]
1618 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1619 "vsqrt%?.f64\\t%P0, %P1"
1620 [(set_attr "predicable" "yes")
1621 (set_attr "predicable_short_it" "no")
1622 (set_attr "arch" "*,armv6_or_vfpv3")
1623 (set_attr "type" "fsqrtd")]
1624 )
1625
1626
1627 ;; Patterns to split/copy vfp condition flags.
1628
1629 (define_insn "*movcc_vfp"
1630 [(set (reg CC_REGNUM)
1631 (reg VFPCC_REGNUM))]
1632 "TARGET_32BIT && TARGET_HARD_FLOAT"
1633 "vmrs%?\\tAPSR_nzcv, FPSCR"
1634 [(set_attr "conds" "set")
1635 (set_attr "type" "f_flag")]
1636 )
1637
1638 (define_insn_and_split "*cmpsf_split_vfp"
1639 [(set (reg:CCFP CC_REGNUM)
1640 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t")
1641 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1642 "TARGET_32BIT && TARGET_HARD_FLOAT"
1643 "#"
1644 "TARGET_32BIT && TARGET_HARD_FLOAT"
1645 [(set (reg:CCFP VFPCC_REGNUM)
1646 (compare:CCFP (match_dup 0)
1647 (match_dup 1)))
1648 (set (reg:CCFP CC_REGNUM)
1649 (reg:CCFP VFPCC_REGNUM))]
1650 ""
1651 )
1652
1653 (define_insn_and_split "*cmpsf_trap_split_vfp"
1654 [(set (reg:CCFPE CC_REGNUM)
1655 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t")
1656 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
1657 "TARGET_32BIT && TARGET_HARD_FLOAT"
1658 "#"
1659 "TARGET_32BIT && TARGET_HARD_FLOAT"
1660 [(set (reg:CCFPE VFPCC_REGNUM)
1661 (compare:CCFPE (match_dup 0)
1662 (match_dup 1)))
1663 (set (reg:CCFPE CC_REGNUM)
1664 (reg:CCFPE VFPCC_REGNUM))]
1665 ""
1666 )
1667
1668 (define_insn_and_split "*cmpdf_split_vfp"
1669 [(set (reg:CCFP CC_REGNUM)
1670 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
1671 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1672 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1673 "#"
1674 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1675 [(set (reg:CCFP VFPCC_REGNUM)
1676 (compare:CCFP (match_dup 0)
1677 (match_dup 1)))
1678 (set (reg:CCFP CC_REGNUM)
1679 (reg:CCFP VFPCC_REGNUM))]
1680 ""
1681 )
1682
1683 (define_insn_and_split "*cmpdf_trap_split_vfp"
1684 [(set (reg:CCFPE CC_REGNUM)
1685 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
1686 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
1687 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1688 "#"
1689 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1690 [(set (reg:CCFPE VFPCC_REGNUM)
1691 (compare:CCFPE (match_dup 0)
1692 (match_dup 1)))
1693 (set (reg:CCFPE CC_REGNUM)
1694 (reg:CCFPE VFPCC_REGNUM))]
1695 ""
1696 )
1697
1698
1699 ;; Comparison patterns
1700
1701 ;; In the compare with FP zero case the ARM Architecture Reference Manual
1702 ;; specifies the immediate to be #0.0. However, some buggy assemblers only
1703 ;; accept #0. We don't want to autodetect broken assemblers, so output #0.
1704 (define_insn "*cmpsf_vfp"
1705 [(set (reg:CCFP VFPCC_REGNUM)
1706 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t,t")
1707 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1708 "TARGET_32BIT && TARGET_HARD_FLOAT"
1709 "@
1710 vcmp%?.f32\\t%0, %1
1711 vcmp%?.f32\\t%0, #0"
1712 [(set_attr "predicable" "yes")
1713 (set_attr "predicable_short_it" "no")
1714 (set_attr "type" "fcmps")]
1715 )
1716
1717 (define_insn "*cmpsf_trap_vfp"
1718 [(set (reg:CCFPE VFPCC_REGNUM)
1719 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t,t")
1720 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
1721 "TARGET_32BIT && TARGET_HARD_FLOAT"
1722 "@
1723 vcmpe%?.f32\\t%0, %1
1724 vcmpe%?.f32\\t%0, #0"
1725 [(set_attr "predicable" "yes")
1726 (set_attr "predicable_short_it" "no")
1727 (set_attr "type" "fcmps")]
1728 )
1729
1730 (define_insn "*cmpdf_vfp"
1731 [(set (reg:CCFP VFPCC_REGNUM)
1732 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
1733 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1734 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1735 "@
1736 vcmp%?.f64\\t%P0, %P1
1737 vcmp%?.f64\\t%P0, #0"
1738 [(set_attr "predicable" "yes")
1739 (set_attr "predicable_short_it" "no")
1740 (set_attr "type" "fcmpd")]
1741 )
1742
1743 (define_insn "*cmpdf_trap_vfp"
1744 [(set (reg:CCFPE VFPCC_REGNUM)
1745 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
1746 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
1747 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1748 "@
1749 vcmpe%?.f64\\t%P0, %P1
1750 vcmpe%?.f64\\t%P0, #0"
1751 [(set_attr "predicable" "yes")
1752 (set_attr "predicable_short_it" "no")
1753 (set_attr "type" "fcmpd")]
1754 )
1755
1756 ;; Fixed point to floating point conversions.
1757 (define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1758 [(set (match_operand:SF 0 "s_register_operand" "=t")
1759 (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
1760 (match_operand 2
1761 "const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1762 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1763 "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2"
1764 [(set_attr "predicable" "yes")
1765 (set_attr "predicable_short_it" "no")
1766 (set_attr "type" "f_cvti2f")]
1767 )
1768
1769 ;; Not the ideal way of implementing this. Ideally we would be able to split
1770 ;; this into a move to a DP register and then a vcvt.f64.i32
1771 (define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1772 [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1773 (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
1774 (match_operand 2
1775 "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
1776 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
1777 && !TARGET_VFP_SINGLE"
1778 "@
1779 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1780 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1781 vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1782 [(set_attr "predicable" "yes")
1783 (set_attr "ce_count" "2")
1784 (set_attr "predicable_short_it" "no")
1785 (set_attr "type" "f_cvti2f")
1786 (set_attr "length" "8")]
1787 )
1788
1789 (define_insn "*combine_vcvtf2i"
1790 [(set (match_operand:SI 0 "s_register_operand" "=t")
1791 (fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0")
1792 (match_operand 2
1793 "const_double_vcvt_power_of_two" "Dp")))))]
1794 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
1795 "vcvt%?.s32.f32\\t%0, %1, %v2"
1796 [(set_attr "predicable" "yes")
1797 (set_attr "predicable_short_it" "no")
1798 (set_attr "type" "f_cvtf2i")]
1799 )
1800
1801 ;; FP16 conversions.
1802 (define_insn "neon_vcvth<sup>hf"
1803 [(set (match_operand:HF 0 "s_register_operand" "=w")
1804 (unspec:HF
1805 [(match_operand:SI 1 "s_register_operand" "w")]
1806 VCVTH_US))]
1807 "TARGET_VFP_FP16INST"
1808 "vcvt.f16.<sup>%#32\t%0, %1"
1809 [(set_attr "conds" "unconditional")
1810 (set_attr "type" "f_cvti2f")]
1811 )
1812
1813 (define_insn "neon_vcvth<sup>si"
1814 [(set (match_operand:SI 0 "s_register_operand" "=w")
1815 (unspec:SI
1816 [(match_operand:HF 1 "s_register_operand" "w")]
1817 VCVTH_US))]
1818 "TARGET_VFP_FP16INST"
1819 "vcvt.<sup>%#32.f16\t%0, %1"
1820 [(set_attr "conds" "unconditional")
1821 (set_attr "type" "f_cvtf2i")]
1822 )
1823
1824 ;; The neon_vcvth<sup>_nhf patterns are used to generate the instruction for the
1825 ;; vcvth_n_f16_<sup>32 arm_fp16 intrinsics. They are complicated by the
1826 ;; hardware requirement that the source and destination registers are the same
1827 ;; despite having different machine modes. The approach is to use a temporary
1828 ;; register for the conversion and move that to the correct destination.
1829
1830 ;; Generate an unspec pattern for the intrinsic.
1831 (define_insn "neon_vcvth<sup>_nhf_unspec"
1832 [(set
1833 (match_operand:SI 0 "s_register_operand" "=w")
1834 (unspec:SI
1835 [(match_operand:SI 1 "s_register_operand" "0")
1836 (match_operand:SI 2 "immediate_operand" "i")]
1837 VCVT_HF_US_N))
1838 (set
1839 (match_operand:HF 3 "s_register_operand" "=w")
1840 (float_truncate:HF (float:SF (match_dup 0))))]
1841 "TARGET_VFP_FP16INST"
1842 {
1843 arm_const_bounds (operands[2], 1, 33);
1844 return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1845 }
1846 [(set_attr "conds" "unconditional")
1847 (set_attr "type" "f_cvti2f")]
1848 )
1849
1850 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1851 (define_expand "neon_vcvth<sup>_nhf"
1852 [(match_operand:HF 0 "s_register_operand")
1853 (unspec:HF [(match_operand:SI 1 "s_register_operand")
1854 (match_operand:SI 2 "immediate_operand")]
1855 VCVT_HF_US_N)]
1856 "TARGET_VFP_FP16INST"
1857 {
1858 rtx op1 = gen_reg_rtx (SImode);
1859
1860 arm_const_bounds (operands[2], 1, 33);
1861
1862 emit_move_insn (op1, operands[1]);
1863 emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2],
1864 operands[0]));
1865 DONE;
1866 })
1867
1868 ;; The neon_vcvth<sup>_nsi patterns are used to generate the instruction for the
1869 ;; vcvth_n_<sup>32_f16 arm_fp16 intrinsics. They have the same restrictions and
1870 ;; are implemented in the same way as the neon_vcvth<sup>_nhf patterns.
1871
1872 ;; Generate an unspec pattern, constraining the registers.
1873 (define_insn "neon_vcvth<sup>_nsi_unspec"
1874 [(set (match_operand:SI 0 "s_register_operand" "=w")
1875 (unspec:SI
1876 [(fix:SI
1877 (fix:SF
1878 (float_extend:SF
1879 (match_operand:HF 1 "s_register_operand" "w"))))
1880 (match_operand:SI 2 "immediate_operand" "i")]
1881 VCVT_SI_US_N))]
1882 "TARGET_VFP_FP16INST"
1883 {
1884 arm_const_bounds (operands[2], 1, 33);
1885 return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1886 }
1887 [(set_attr "conds" "unconditional")
1888 (set_attr "type" "f_cvtf2i")]
1889 )
1890
1891 ;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1892 (define_expand "neon_vcvth<sup>_nsi"
1893 [(match_operand:SI 0 "s_register_operand")
1894 (unspec:SI
1895 [(match_operand:HF 1 "s_register_operand")
1896 (match_operand:SI 2 "immediate_operand")]
1897 VCVT_SI_US_N)]
1898 "TARGET_VFP_FP16INST"
1899 {
1900 rtx op1 = gen_reg_rtx (SImode);
1901
1902 arm_const_bounds (operands[2], 1, 33);
1903 emit_insn (gen_neon_vcvth<sup>_nsi_unspec (op1, operands[1], operands[2]));
1904 emit_move_insn (operands[0], op1);
1905 DONE;
1906 })
1907
1908 (define_insn "neon_vcvt<vcvth_op>h<sup>si"
1909 [(set
1910 (match_operand:SI 0 "s_register_operand" "=w")
1911 (unspec:SI
1912 [(match_operand:HF 1 "s_register_operand" "w")]
1913 VCVT_HF_US))]
1914 "TARGET_VFP_FP16INST"
1915 "vcvt<vcvth_op>.<sup>%#32.f16\t%0, %1"
1916 [(set_attr "conds" "unconditional")
1917 (set_attr "type" "f_cvtf2i")]
1918 )
1919
1920 ;; Store multiple insn used in function prologue.
1921 (define_insn "*push_multi_vfp"
1922 [(match_parallel 2 "multi_register_push"
1923 [(set (match_operand:BLK 0 "memory_operand" "=m")
1924 (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
1925 UNSPEC_PUSH_MULT))])]
1926 "TARGET_32BIT && TARGET_HARD_FLOAT"
1927 "* return vfp_output_vstmd (operands);"
1928 [(set_attr "type" "f_stored")]
1929 )
1930
1931 ;; VRINT round to integral instructions.
1932 ;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
1933 ;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
1934 ;; rintsf2, rintdf2.
1935 (define_insn "<vrint_pattern><SDF:mode>2"
1936 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1937 (unspec:SDF [(match_operand:SDF 1
1938 "register_operand" "<F_constraint>")]
1939 VRINT))]
1940 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1941 "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
1942 [(set_attr "predicable" "<vrint_predicable>")
1943 (set_attr "predicable_short_it" "no")
1944 (set_attr "type" "f_rint<vfp_type>")
1945 (set_attr "conds" "<vrint_conds>")]
1946 )
1947
1948 ;; Implements the lround, lfloor and lceil optabs.
1949 (define_insn "l<vrint_pattern><su_optab><mode>si2"
1950 [(set (match_operand:SI 0 "register_operand" "=t")
1951 (FIXUORS:SI (unspec:SDF
1952 [(match_operand:SDF 1
1953 "register_operand" "<F_constraint>")] VCVT)))]
1954 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1955 "vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1"
1956 [(set_attr "predicable" "no")
1957 (set_attr "conds" "unconditional")
1958 (set_attr "type" "f_cvtf2i")]
1959 )
1960
1961 ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
1962 ;; The 'smax' and 'smin' RTL standard pattern names do not specify which
1963 ;; operand will be returned when both operands are zero (i.e. they may not
1964 ;; honour signed zeroes), or when either operand is NaN. Therefore GCC
1965 ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
1966 ;; NaNs.
1967
1968 (define_insn "smax<mode>3"
1969 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1970 (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1971 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1972 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1973 "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1974 [(set_attr "type" "f_minmax<vfp_type>")
1975 (set_attr "conds" "unconditional")]
1976 )
1977
1978 (define_insn "smin<mode>3"
1979 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1980 (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
1981 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
1982 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1983 "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1984 [(set_attr "type" "f_minmax<vfp_type>")
1985 (set_attr "conds" "unconditional")]
1986 )
1987
1988 ;; Scalar forms for the IEEE-754 fmax()/fmin() functions
1989
1990 (define_insn "neon_<fmaxmin_op>hf"
1991 [(set
1992 (match_operand:HF 0 "s_register_operand" "=w")
1993 (unspec:HF
1994 [(match_operand:HF 1 "s_register_operand" "w")
1995 (match_operand:HF 2 "s_register_operand" "w")]
1996 VMAXMINFNM))]
1997 "TARGET_VFP_FP16INST"
1998 "<fmaxmin_op>.f16\t%0, %1, %2"
1999 [(set_attr "conds" "unconditional")
2000 (set_attr "type" "f_minmaxs")]
2001 )
2002
2003 (define_insn "<fmaxmin><mode>3"
2004 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
2005 (unspec:SDF [(match_operand:SDF 1 "s_register_operand" "<F_constraint>")
2006 (match_operand:SDF 2 "s_register_operand" "<F_constraint>")]
2007 VMAXMINFNM))]
2008 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2009 "<fmaxmin_op>.<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 ;; Write Floating-point Status and Control Register.
2015 (define_insn "set_fpscr"
2016 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)]
2017 "TARGET_HARD_FLOAT"
2018 "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
2019 [(set_attr "type" "mrs")])
2020
2021 ;; Read Floating-point Status and Control Register.
2022 (define_insn "get_fpscr"
2023 [(set (match_operand:SI 0 "register_operand" "=r")
2024 (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
2025 "TARGET_HARD_FLOAT"
2026 "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
2027 [(set_attr "type" "mrs")])
2028
2029
2030 ;; Unimplemented insns:
2031 ;; fldm*
2032 ;; fstm*
2033 ;; fmdhr et al (VFPv1)
2034 ;; Support for xD (single precision only) variants.
2035 ;; fmrrs, fmsrr
2036
2037 ;; Split an immediate DF move to two immediate SI moves.
2038 (define_insn_and_split "no_literal_pool_df_immediate"
2039 [(set (match_operand:DF 0 "s_register_operand" "")
2040 (match_operand:DF 1 "const_double_operand" ""))]
2041 "TARGET_THUMB2 && arm_disable_literal_pool
2042 && !(TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
2043 && vfp3_const_double_rtx (operands[1]))"
2044 "#"
2045 "&& !reload_completed"
2046 [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
2047 (set (subreg:SI (match_dup 1) 4) (match_dup 3))
2048 (set (match_dup 0) (match_dup 1))]
2049 "
2050 long buf[2];
2051 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
2052 operands[2] = GEN_INT ((int) buf[0]);
2053 operands[3] = GEN_INT ((int) buf[1]);
2054 operands[1] = gen_reg_rtx (DFmode);
2055 ")
2056
2057 ;; Split an immediate SF move to one immediate SI move.
2058 (define_insn_and_split "no_literal_pool_sf_immediate"
2059 [(set (match_operand:SF 0 "s_register_operand" "")
2060 (match_operand:SF 1 "const_double_operand" ""))]
2061 "TARGET_THUMB2 && arm_disable_literal_pool
2062 && !(TARGET_HARD_FLOAT && vfp3_const_double_rtx (operands[1]))"
2063 "#"
2064 "&& !reload_completed"
2065 [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
2066 (set (match_dup 0) (match_dup 1))]
2067 "
2068 long buf;
2069 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
2070 operands[2] = GEN_INT ((int) buf);
2071 operands[1] = gen_reg_rtx (SFmode);
2072 ")