]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/vfp.md
c/c++: Add fix-it hints for suggested missing #includes
[thirdparty/gcc.git] / gcc / config / arm / vfp.md
CommitLineData
3f4d9b98 1;; ARM VFP instruction patterns
cbe34bb5 2;; Copyright (C) 2003-2017 Free Software Foundation, Inc.
3f4d9b98 3;; Written by CodeSourcery.
9b66ebb1
PB
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
2f83c7d6 9;; the Free Software Foundation; either version 3, or (at your option)
9b66ebb1
PB
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
2f83c7d6
NC
18;; along with GCC; see the file COPYING3. If not see
19;; <http://www.gnu.org/licenses/>. */
9b66ebb1 20
50df9464
MW
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"))]
00ea1506 29 "TARGET_ARM && TARGET_HARD_FLOAT
4ffc8099 30 && !TARGET_VFP_FP16INST
50df9464
MW
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")])
69ba69c9 68 (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
50df9464
MW
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"))]
00ea1506 80 "TARGET_THUMB2 && TARGET_HARD_FLOAT
4ffc8099 81 && !TARGET_VFP_FP16INST
50df9464
MW
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")
69ba69c9 112 (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *")
50df9464
MW
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
4ffc8099
MW
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:
5b2b17db 144 return "vmov.f16\t%0, %1\t%@ int";
4ffc8099
MW
145 case 7:
146 return "vmov%?.f32\t%0, %1\t%@ int";
147 default:
148 gcc_unreachable ();
149 }
150}
5b2b17db 151 [(set_attr "predicable" "yes, yes, yes, yes, yes, no, no, yes")
4ffc8099
MW
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")])
69ba69c9 164 (set_attr "arch" "*, *, v6t2, *, *, *, *, *")
4ffc8099
MW
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:
5b2b17db 194 return "vmov.f16\t%0, %1\t%@ int";
4ffc8099
MW
195 case 8:
196 return "vmov%?.f32\t%0, %1\t%@ int";
197 default:
198 gcc_unreachable ();
199 }
200}
5b2b17db
MW
201 [(set_attr "predicable"
202 "yes, yes, yes, yes, yes, yes, no, no, yes")
4ffc8099
MW
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")
69ba69c9 208 (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *")
4ffc8099
MW
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
9b66ebb1
PB
214;; SImode moves
215;; ??? For now do not allow loading constants into vfp regs. This causes
59b9a953 216;; problems because small constants get converted into adds.
9b66ebb1 217(define_insn "*arm_movsi_vfp"
f5c630c3 218 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv")
d58bc084 219 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk,r,*t,*t,*Uvi,*t"))]
00ea1506 220 "TARGET_ARM && TARGET_HARD_FLOAT
9b66ebb1
PB
221 && ( s_register_operand (operands[0], SImode)
222 || s_register_operand (operands[1], SImode))"
5b3e6663
PB
223 "*
224 switch (which_alternative)
225 {
f5c630c3 226 case 0: case 1:
5b3e6663 227 return \"mov%?\\t%0, %1\";
5b3e6663 228 case 2:
f5c630c3 229 return \"mvn%?\\t%0, #%B1\";
5b3e6663 230 case 3:
f5c630c3 231 return \"movw%?\\t%0, %1\";
5b3e6663 232 case 4:
f5c630c3 233 return \"ldr%?\\t%0, %1\";
5b3e6663 234 case 5:
f5c630c3 235 return \"str%?\\t%1, %0\";
5b3e6663 236 case 6:
35cb3e53 237 return \"vmov%?\\t%0, %1\\t%@ int\";
5b3e6663 238 case 7:
35cb3e53 239 return \"vmov%?\\t%0, %1\\t%@ int\";
f5c630c3 240 case 8:
35cb3e53 241 return \"vmov%?.f32\\t%0, %1\\t%@ int\";
f5c630c3 242 case 9: case 10:
5b3e6663
PB
243 return output_move_vfp (operands);
244 default:
245 gcc_unreachable ();
246 }
247 "
248 [(set_attr "predicable" "yes")
5b2b17db
MW
249 (set_attr "type" "mov_reg,mov_reg,mvn_imm,mov_imm,load1,store1,
250 f_mcr,f_mrc,fmov,f_loads,f_stores")
f5c630c3
PB
251 (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*")
252 (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")]
5b3e6663
PB
253)
254
28907f9a
MS
255;; See thumb2.md:thumb2_movsi_insn for an explanation of the split
256;; high/low register alternatives for loads and stores here.
956a95a5
KT
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.
5b3e6663 260(define_insn "*thumb2_movsi_vfp"
956a95a5
KT
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"))]
00ea1506 263 "TARGET_THUMB2 && TARGET_HARD_FLOAT
5b3e6663
PB
264 && ( s_register_operand (operands[0], SImode)
265 || s_register_operand (operands[1], SImode))"
266 "*
267 switch (which_alternative)
268 {
956a95a5
KT
269 case 0:
270 case 1:
5b3e6663 271 case 2:
956a95a5 272 return \"mov%?\\t%0, %1\";
5b3e6663 273 case 3:
956a95a5 274 return \"mvn%?\\t%0, #%B1\";
5b3e6663 275 case 4:
956a95a5 276 return \"movw%?\\t%0, %1\";
5b3e6663 277 case 5:
5b3e6663 278 case 6:
956a95a5 279 return \"ldr%?\\t%0, %1\";
5b3e6663 280 case 7:
f5c630c3 281 case 8:
956a95a5 282 return \"str%?\\t%1, %0\";
28907f9a 283 case 9:
35cb3e53 284 return \"vmov%?\\t%0, %1\\t%@ int\";
28907f9a 285 case 10:
35cb3e53 286 return \"vmov%?\\t%0, %1\\t%@ int\";
956a95a5 287 case 11:
35cb3e53 288 return \"vmov%?.f32\\t%0, %1\\t%@ int\";
956a95a5 289 case 12: case 13:
5b3e6663
PB
290 return output_move_vfp (operands);
291 default:
292 gcc_unreachable ();
293 }
294 "
9b66ebb1 295 [(set_attr "predicable" "yes")
956a95a5 296 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no")
56912037 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")
956a95a5 298 (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4")
956a95a5
KT
299 (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*")
300 (set_attr "neg_pool_range" "*,*,*,*,*, 0, 0,*,*,*,*,*,1008,*")]
9b66ebb1
PB
301)
302
303
304;; DImode moves
305
0127c76f 306(define_insn "*movdi_vfp"
4542a38a
GY
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"))]
b854516c 309 "TARGET_32BIT && TARGET_HARD_FLOAT && arm_tune != TARGET_CPU_cortexa8
7baa7c13 310 && ( register_operand (operands[0], DImode)
00a3a76a
AS
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))"
7baa7c13
BS
314 "*
315 switch (which_alternative)
316 {
317 case 0:
7baa7c13
BS
318 case 1:
319 case 2:
7baa7c13 320 case 3:
0127c76f 321 return \"#\";
7baa7c13 322 case 4:
7baa7c13 323 case 5:
0127c76f 324 case 6:
3598da80 325 return output_move_double (operands, true, NULL);
0127c76f 326 case 7:
35cb3e53 327 return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\";
0127c76f 328 case 8:
35cb3e53 329 return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\";
0127c76f 330 case 9:
7baa7c13 331 if (TARGET_VFP_SINGLE)
35cb3e53 332 return \"vmov%?.f32\\t%0, %1\\t%@ int\;vmov%?.f32\\t%p0, %p1\\t%@ int\";
7baa7c13 333 else
35cb3e53 334 return \"vmov%?.f64\\t%P0, %P1\\t%@ int\";
0127c76f 335 case 10: case 11:
7baa7c13
BS
336 return output_move_vfp (operands);
337 default:
338 gcc_unreachable ();
339 }
340 "
594726e4 341 [(set_attr "type" "multiple,multiple,multiple,multiple,load2,load2,store2,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored")
0127c76f
RR
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
b75b1be2 347 (match_test "TARGET_VFP_SINGLE")
0127c76f
RR
348 (const_int 8)
349 (const_int 4))]
350 (const_int 4)))
88f519b2
MGD
351 (set_attr "arm_pool_range" "*,*,*,*,1020,4096,*,*,*,*,1020,*")
352 (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
635a48fb 353 (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
0127c76f 354 (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
7baa7c13
BS
355)
356
0127c76f 357(define_insn "*movdi_vfp_cortexa8"
c69fb816
KT
358 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,q,q,m,w,!r,w,w, Uv")
359 (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,q,r,w,w,Uvi,w"))]
b854516c 360 "TARGET_32BIT && TARGET_HARD_FLOAT && arm_tune == TARGET_CPU_cortexa8
0127c76f 361 && ( register_operand (operands[0], DImode)
00a3a76a
AS
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))"
9b66ebb1
PB
365 "*
366 switch (which_alternative)
367 {
9b901d50 368 case 0:
9b901d50
RE
369 case 1:
370 case 2:
9b66ebb1 371 case 3:
0127c76f 372 return \"#\";
9b66ebb1 373 case 4:
9b66ebb1 374 case 5:
0127c76f 375 case 6:
3598da80 376 return output_move_double (operands, true, NULL);
0127c76f 377 case 7:
35cb3e53 378 return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\";
0127c76f 379 case 8:
35cb3e53 380 return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\";
0127c76f 381 case 9:
35cb3e53 382 return \"vmov%?.f64\\t%P0, %P1\\t%@ int\";
0127c76f 383 case 10: case 11:
5b3e6663
PB
384 return output_move_vfp (operands);
385 default:
0127c76f 386 gcc_unreachable ();
5b3e6663
PB
387 }
388 "
594726e4 389 [(set_attr "type" "multiple,multiple,multiple,multiple,load2,load2,store2,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored")
3598da80
RR
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)))
0127c76f 398 (set_attr "predicable" "yes")
88f519b2
MGD
399 (set_attr "arm_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
400 (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*")
635a48fb 401 (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*")
3598da80
RR
402 (set (attr "ce_count")
403 (symbol_ref "get_attr_length (insn) / 4"))
0127c76f
RR
404 (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
405 )
5b3e6663 406
0fd8c3ad 407;; HFmode moves
4ffc8099
MW
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
e0dc3601 483(define_insn "*movhf_vfp_neon"
0fd8c3ad
SL
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"))]
4ffc8099
MW
486 "TARGET_32BIT
487 && TARGET_HARD_FLOAT && TARGET_NEON_FP16
488 && !TARGET_VFP_FP16INST
0fd8c3ad
SL
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 */
35cb3e53 503 return \"vmov.f32\\t%0, %1\";
0fd8c3ad
SL
504 case 5: /* ARM register from ARM register */
505 return \"mov\\t%0, %1\\t%@ __fp16\";
506 case 6: /* S register from ARM register */
35cb3e53 507 return \"vmov\\t%0, %1\";
0fd8c3ad 508 case 7: /* ARM register from S register */
35cb3e53 509 return \"vmov\\t%0, %1\";
0fd8c3ad
SL
510 case 8: /* ARM register from constant */
511 {
0fd8c3ad
SL
512 long bits;
513 rtx ops[4];
514
34a72c33
RS
515 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
516 HFmode);
0fd8c3ad
SL
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")
f7379e5e 533 (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\
292b89b3 534 load1,store1,fmov,mov_reg,f_mcr,f_mrc,multiple")
0fd8c3ad
SL
535 (set_attr "length" "4,4,4,4,4,4,4,4,8")]
536)
537
e0dc3601
PB
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"))]
4ffc8099 542 "TARGET_32BIT
00ea1506 543 && TARGET_HARD_FLOAT
1b81a1c1 544 && !TARGET_NEON_FP16
4ffc8099 545 && !TARGET_VFP_FP16INST
e0dc3601
PB
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 */
35cb3e53 556 return \"vmov.f32\\t%0, %1\";
e0dc3601
PB
557 case 3: /* ARM register from ARM register */
558 return \"mov\\t%0, %1\\t%@ __fp16\";
559 case 4: /* S register from ARM register */
35cb3e53 560 return \"vmov\\t%0, %1\";
e0dc3601 561 case 5: /* ARM register from S register */
35cb3e53 562 return \"vmov\\t%0, %1\";
e0dc3601
PB
563 case 6: /* ARM register from constant */
564 {
e0dc3601
PB
565 long bits;
566 rtx ops[4];
567
34a72c33
RS
568 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
569 HFmode);
e0dc3601
PB
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")
292b89b3 586 (set_attr "type" "load1,store1,fmov,mov_reg,f_mcr,f_mrc,multiple")
e0dc3601
PB
587 (set_attr "length" "4,4,4,4,4,4,8")]
588)
589
9b66ebb1
PB
590
591;; SFmode moves
221b2a64
PB
592;; Disparage the w<->r cases because reloading an invalid address is
593;; preferable to loading the value via integer registers.
9b66ebb1
PB
594
595(define_insn "*movsf_vfp"
f1adb0a9 596 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t ,Uv,r ,m,t,r")
35cb3e53 597 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))]
00ea1506 598 "TARGET_ARM && TARGET_HARD_FLOAT
9b66ebb1
PB
599 && ( s_register_operand (operands[0], SFmode)
600 || s_register_operand (operands[1], SFmode))"
5b3e6663
PB
601 "*
602 switch (which_alternative)
603 {
604 case 0:
35cb3e53 605 return \"vmov%?\\t%0, %1\";
5b3e6663 606 case 1:
35cb3e53 607 return \"vmov%?\\t%0, %1\";
f1adb0a9 608 case 2:
35cb3e53 609 return \"vmov%?.f32\\t%0, %1\";
f1adb0a9 610 case 3: case 4:
5b3e6663 611 return output_move_vfp (operands);
5b3e6663 612 case 5:
f1adb0a9 613 return \"ldr%?\\t%0, %1\\t%@ float\";
5b3e6663 614 case 6:
f1adb0a9 615 return \"str%?\\t%1, %0\\t%@ float\";
5b3e6663 616 case 7:
35cb3e53 617 return \"vmov%?.f32\\t%0, %1\";
f1adb0a9 618 case 8:
5b3e6663
PB
619 return \"mov%?\\t%0, %1\\t%@ float\";
620 default:
621 gcc_unreachable ();
622 }
623 "
9b66ebb1 624 [(set_attr "predicable" "yes")
f1adb0a9 625 (set_attr "type"
292b89b3 626 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load1,store1,fmov,mov_reg")
f1adb0a9
JB
627 (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
628 (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
9b66ebb1
PB
629)
630
5b3e6663 631(define_insn "*thumb2_movsf_vfp"
f1adb0a9
JB
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"))]
00ea1506 634 "TARGET_THUMB2 && TARGET_HARD_FLOAT
5b3e6663
PB
635 && ( s_register_operand (operands[0], SFmode)
636 || s_register_operand (operands[1], SFmode))"
637 "*
638 switch (which_alternative)
639 {
640 case 0:
35cb3e53 641 return \"vmov%?\\t%0, %1\";
5b3e6663 642 case 1:
35cb3e53 643 return \"vmov%?\\t%0, %1\";
f1adb0a9 644 case 2:
35cb3e53 645 return \"vmov%?.f32\\t%0, %1\";
f1adb0a9 646 case 3: case 4:
5b3e6663 647 return output_move_vfp (operands);
5b3e6663 648 case 5:
f1adb0a9 649 return \"ldr%?\\t%0, %1\\t%@ float\";
5b3e6663 650 case 6:
f1adb0a9 651 return \"str%?\\t%1, %0\\t%@ float\";
5b3e6663 652 case 7:
35cb3e53 653 return \"vmov%?.f32\\t%0, %1\";
f1adb0a9 654 case 8:
5b3e6663
PB
655 return \"mov%?\\t%0, %1\\t%@ float\";
656 default:
657 gcc_unreachable ();
658 }
659 "
660 [(set_attr "predicable" "yes")
1572e697 661 (set_attr "predicable_short_it" "no")
f1adb0a9 662 (set_attr "type"
292b89b3 663 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load1,store1,fmov,mov_reg")
88f519b2 664 (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*")
f1adb0a9 665 (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
5b3e6663
PB
666)
667
9b66ebb1
PB
668;; DFmode moves
669
670(define_insn "*movdf_vfp"
c76623e7
JW
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"))]
00ea1506 673 "TARGET_ARM && TARGET_HARD_FLOAT
d5b6e637
PB
674 && ( register_operand (operands[0], DFmode)
675 || register_operand (operands[1], DFmode))"
9b66ebb1
PB
676 "*
677 {
678 switch (which_alternative)
679 {
680 case 0:
35cb3e53 681 return \"vmov%?\\t%P0, %Q1, %R1\";
9b66ebb1 682 case 1:
35cb3e53 683 return \"vmov%?\\t%Q0, %R0, %P1\";
f1adb0a9 684 case 2:
e0dc3601 685 gcc_assert (TARGET_VFP_DOUBLE);
35cb3e53 686 return \"vmov%?.f64\\t%P0, %1\";
c76623e7
JW
687 case 3:
688 gcc_assert (TARGET_VFP_DOUBLE);
689 return \"vmov.i64\\t%P0, #0\\t%@ float\";
690 case 4: case 5:
5b3e6663 691 return output_move_vfp (operands);
c76623e7 692 case 6: case 7:
3598da80 693 return output_move_double (operands, true, NULL);
c76623e7 694 case 8:
e0dc3601 695 if (TARGET_VFP_SINGLE)
35cb3e53 696 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
e0dc3601 697 else
35cb3e53 698 return \"vmov%?.f64\\t%P0, %P1\";
c76623e7 699 case 9:
9b901d50 700 return \"#\";
9b66ebb1 701 default:
e6d29d15 702 gcc_unreachable ();
9b66ebb1
PB
703 }
704 }
705 "
c76623e7 706 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,f_stored,\
594726e4 707 load2,store2,ffarithd,multiple")
c76623e7
JW
708 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
709 (eq_attr "alternative" "8")
e0dc3601 710 (if_then_else
b75b1be2 711 (match_test "TARGET_VFP_SINGLE")
e0dc3601
PB
712 (const_int 8)
713 (const_int 4))]
714 (const_int 4)))
c76623e7
JW
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")]
9b66ebb1
PB
719)
720
5b3e6663 721(define_insn "*thumb2_movdf_vfp"
c76623e7
JW
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"))]
00ea1506 724 "TARGET_THUMB2 && TARGET_HARD_FLOAT
de7c74be
RB
725 && ( register_operand (operands[0], DFmode)
726 || register_operand (operands[1], DFmode))"
5b3e6663
PB
727 "*
728 {
729 switch (which_alternative)
730 {
731 case 0:
35cb3e53 732 return \"vmov%?\\t%P0, %Q1, %R1\";
5b3e6663 733 case 1:
35cb3e53 734 return \"vmov%?\\t%Q0, %R0, %P1\";
f1adb0a9 735 case 2:
e0dc3601 736 gcc_assert (TARGET_VFP_DOUBLE);
35cb3e53 737 return \"vmov%?.f64\\t%P0, %1\";
c76623e7
JW
738 case 3:
739 gcc_assert (TARGET_VFP_DOUBLE);
740 return \"vmov.i64\\t%P0, #0\\t%@ float\";
741 case 4: case 5:
5b3e6663 742 return output_move_vfp (operands);
c76623e7 743 case 6: case 7: case 9:
3598da80 744 return output_move_double (operands, true, NULL);
c76623e7 745 case 8:
e0dc3601 746 if (TARGET_VFP_SINGLE)
35cb3e53 747 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\";
e0dc3601 748 else
35cb3e53 749 return \"vmov%?.f64\\t%P0, %P1\";
5b3e6663
PB
750 default:
751 abort ();
752 }
753 }
754 "
c76623e7 755 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,\
594726e4 756 f_stored,load2,store2,ffarithd,multiple")
c76623e7
JW
757 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8)
758 (eq_attr "alternative" "8")
e0dc3601 759 (if_then_else
b75b1be2 760 (match_test "TARGET_VFP_SINGLE")
e0dc3601
PB
761 (const_int 8)
762 (const_int 4))]
763 (const_int 4)))
c76623e7
JW
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")]
5b3e6663
PB
767)
768
9b66ebb1
PB
769
770;; Conditional move patterns
771
772(define_insn "*movsfcc_vfp"
f1adb0a9 773 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
9b66ebb1
PB
774 (if_then_else:SF
775 (match_operator 3 "arm_comparison_operator"
776 [(match_operand 4 "cc_register" "") (const_int 0)])
f1adb0a9
JB
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")))]
00ea1506 779 "TARGET_ARM && TARGET_HARD_FLOAT"
9b66ebb1 780 "@
35cb3e53
KT
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"
9b66ebb1
PB
790 [(set_attr "conds" "use")
791 (set_attr "length" "4,4,8,4,4,8,4,4,8")
292b89b3 792 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
9b66ebb1
PB
793)
794
5b3e6663 795(define_insn "*thumb2_movsfcc_vfp"
f1adb0a9 796 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
5b3e6663
PB
797 (if_then_else:SF
798 (match_operator 3 "arm_comparison_operator"
799 [(match_operand 4 "cc_register" "") (const_int 0)])
f1adb0a9
JB
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")))]
00ea1506 802 "TARGET_THUMB2 && TARGET_HARD_FLOAT && !arm_restrict_it"
5b3e6663 803 "@
35cb3e53
KT
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"
5b3e6663
PB
813 [(set_attr "conds" "use")
814 (set_attr "length" "6,6,10,6,6,10,6,6,10")
292b89b3 815 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")]
5b3e6663
PB
816)
817
9b66ebb1
PB
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")))]
e0dc3601 825 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
9b66ebb1 826 "@
35cb3e53
KT
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"
9b66ebb1
PB
836 [(set_attr "conds" "use")
837 (set_attr "length" "4,4,8,4,4,8,4,4,8")
003bb7f3 838 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcr,f_mrrc,f_mrrc,f_mrrc")]
9b66ebb1
PB
839)
840
5b3e6663
PB
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")))]
1572e697 848 "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && !arm_restrict_it"
5b3e6663 849 "@
35cb3e53
KT
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"
5b3e6663
PB
859 [(set_attr "conds" "use")
860 (set_attr "length" "6,6,10,6,6,10,6,6,10")
594726e4 861 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcrr,f_mrrc,f_mrrc,f_mrrc")]
5b3e6663
PB
862)
863
9b66ebb1
PB
864
865;; Sign manipulation functions
866
867(define_insn "*abssf2_vfp"
f1adb0a9
JB
868 [(set (match_operand:SF 0 "s_register_operand" "=t")
869 (abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
00ea1506 870 "TARGET_32BIT && TARGET_HARD_FLOAT"
436c249d 871 "vabs%?.f32\\t%0, %1"
9b66ebb1 872 [(set_attr "predicable" "yes")
1572e697 873 (set_attr "predicable_short_it" "no")
51c69ddb 874 (set_attr "type" "ffariths")]
9b66ebb1
PB
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")))]
e0dc3601 880 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
436c249d 881 "vabs%?.f64\\t%P0, %P1"
9b66ebb1 882 [(set_attr "predicable" "yes")
1572e697 883 (set_attr "predicable_short_it" "no")
51c69ddb 884 (set_attr "type" "ffarithd")]
9b66ebb1
PB
885)
886
887(define_insn "*negsf2_vfp"
f1adb0a9
JB
888 [(set (match_operand:SF 0 "s_register_operand" "=t,?r")
889 (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))]
00ea1506 890 "TARGET_32BIT && TARGET_HARD_FLOAT"
81632f11 891 "@
436c249d 892 vneg%?.f32\\t%0, %1
81632f11 893 eor%?\\t%0, %1, #-2147483648"
9b66ebb1 894 [(set_attr "predicable" "yes")
1572e697 895 (set_attr "predicable_short_it" "no")
51c69ddb 896 (set_attr "type" "ffariths")]
9b66ebb1
PB
897)
898
81632f11
RE
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")))]
e0dc3601 902 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
81632f11 903 "@
436c249d 904 vneg%?.f64\\t%P0, %P1
81632f11
RE
905 #
906 #"
e0dc3601 907 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
81632f11
RE
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 {
f7df4a84 928 emit_insn (gen_rtx_SET (out_lo, in_lo));
81632f11
RE
929 operands[0] = out_hi;
930 operands[1] = in_hi;
931 }
932 else
933 {
f7df4a84 934 emit_insn (gen_rtx_SET (out_hi, in_hi));
81632f11
RE
935 operands[0] = out_lo;
936 operands[1] = in_lo;
937 }
938 }
939 "
9b66ebb1 940 [(set_attr "predicable" "yes")
1572e697 941 (set_attr "predicable_short_it" "no")
81632f11 942 (set_attr "length" "4,4,8")
51c69ddb 943 (set_attr "type" "ffarithd")]
9b66ebb1
PB
944)
945
d403b8d4
MW
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)
9b66ebb1
PB
988
989;; Arithmetic insns
990
d403b8d4
MW
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
9b66ebb1 1003(define_insn "*addsf3_vfp"
f1adb0a9
JB
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")))]
00ea1506 1007 "TARGET_32BIT && TARGET_HARD_FLOAT"
436c249d 1008 "vadd%?.f32\\t%0, %1, %2"
9b66ebb1 1009 [(set_attr "predicable" "yes")
1572e697 1010 (set_attr "predicable_short_it" "no")
51c69ddb 1011 (set_attr "type" "fadds")]
9b66ebb1
PB
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")))]
e0dc3601 1018 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
436c249d 1019 "vadd%?.f64\\t%P0, %P1, %P2"
9b66ebb1 1020 [(set_attr "predicable" "yes")
1572e697 1021 (set_attr "predicable_short_it" "no")
51c69ddb 1022 (set_attr "type" "faddd")]
9b66ebb1
PB
1023)
1024
d403b8d4
MW
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)
9b66ebb1
PB
1036
1037(define_insn "*subsf3_vfp"
f1adb0a9
JB
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")))]
00ea1506 1041 "TARGET_32BIT && TARGET_HARD_FLOAT"
436c249d 1042 "vsub%?.f32\\t%0, %1, %2"
9b66ebb1 1043 [(set_attr "predicable" "yes")
1572e697 1044 (set_attr "predicable_short_it" "no")
51c69ddb 1045 (set_attr "type" "fadds")]
9b66ebb1
PB
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")))]
e0dc3601 1052 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
436c249d 1053 "vsub%?.f64\\t%P0, %P1, %P2"
9b66ebb1 1054 [(set_attr "predicable" "yes")
1572e697 1055 (set_attr "predicable_short_it" "no")
51c69ddb 1056 (set_attr "type" "faddd")]
9b66ebb1
PB
1057)
1058
1059
1060;; Division insns
1061
d403b8d4
MW
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
a89b02c0
RE
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.
9b66ebb1 1078(define_insn "*divsf3_vfp"
a89b02c0
RE
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")))]
00ea1506 1082 "TARGET_32BIT && TARGET_HARD_FLOAT"
436c249d 1083 "vdiv%?.f32\\t%0, %1, %2"
9b66ebb1 1084 [(set_attr "predicable" "yes")
1572e697 1085 (set_attr "predicable_short_it" "no")
a89b02c0 1086 (set_attr "arch" "*,armv6_or_vfpv3")
9b66ebb1
PB
1087 (set_attr "type" "fdivs")]
1088)
1089
1090(define_insn "*divdf3_vfp"
a89b02c0
RE
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")))]
e0dc3601 1094 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
436c249d 1095 "vdiv%?.f64\\t%P0, %P1, %P2"
9b66ebb1 1096 [(set_attr "predicable" "yes")
1572e697 1097 (set_attr "predicable_short_it" "no")
a89b02c0 1098 (set_attr "arch" "*,armv6_or_vfpv3")
9b66ebb1
PB
1099 (set_attr "type" "fdivd")]
1100)
1101
1102
1103;; Multiplication insns
1104
d403b8d4
MW
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
9b66ebb1 1116(define_insn "*mulsf3_vfp"
0498a2be 1117 [(set (match_operand:SF 0 "s_register_operand" "=t")
f1adb0a9
JB
1118 (mult:SF (match_operand:SF 1 "s_register_operand" "t")
1119 (match_operand:SF 2 "s_register_operand" "t")))]
00ea1506 1120 "TARGET_32BIT && TARGET_HARD_FLOAT"
14d9aa9f 1121 "vmul%?.f32\\t%0, %1, %2"
9b66ebb1 1122 [(set_attr "predicable" "yes")
1572e697 1123 (set_attr "predicable_short_it" "no")
a8e17e9e 1124 (set_attr "type" "fmuls")]
9b66ebb1
PB
1125)
1126
1127(define_insn "*muldf3_vfp"
0498a2be 1128 [(set (match_operand:DF 0 "s_register_operand" "=w")
9b66ebb1
PB
1129 (mult:DF (match_operand:DF 1 "s_register_operand" "w")
1130 (match_operand:DF 2 "s_register_operand" "w")))]
e0dc3601 1131 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14d9aa9f 1132 "vmul%?.f64\\t%P0, %P1, %P2"
9b66ebb1 1133 [(set_attr "predicable" "yes")
1572e697 1134 (set_attr "predicable_short_it" "no")
a8e17e9e 1135 (set_attr "type" "fmuld")]
9b66ebb1
PB
1136)
1137
d403b8d4
MW
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
9b66ebb1 1158(define_insn "*mulsf3negsf_vfp"
0498a2be 1159 [(set (match_operand:SF 0 "s_register_operand" "=t")
f1adb0a9
JB
1160 (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
1161 (match_operand:SF 2 "s_register_operand" "t")))]
00ea1506 1162 "TARGET_32BIT && TARGET_HARD_FLOAT && !flag_rounding_math"
1f71aee9
SN
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"))))]
00ea1506 1173 "TARGET_32BIT && TARGET_HARD_FLOAT"
14d9aa9f 1174 "vnmul%?.f32\\t%0, %1, %2"
9b66ebb1 1175 [(set_attr "predicable" "yes")
1572e697 1176 (set_attr "predicable_short_it" "no")
a8e17e9e 1177 (set_attr "type" "fmuls")]
9b66ebb1
PB
1178)
1179
1180(define_insn "*muldf3negdf_vfp"
0498a2be 1181 [(set (match_operand:DF 0 "s_register_operand" "=w")
9b66ebb1
PB
1182 (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
1183 (match_operand:DF 2 "s_register_operand" "w")))]
1f71aee9
SN
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"))))]
e0dc3601 1196 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14d9aa9f 1197 "vnmul%?.f64\\t%P0, %P1, %P2"
9b66ebb1 1198 [(set_attr "predicable" "yes")
1572e697 1199 (set_attr "predicable_short_it" "no")
a8e17e9e 1200 (set_attr "type" "fmuld")]
9b66ebb1
PB
1201)
1202
1203
1204;; Multiply-accumulate insns
1205
1206;; 0 = 1 * 2 + 0
d403b8d4
MW
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
9b66ebb1 1219(define_insn "*mulsf3addsf_vfp"
f1adb0a9
JB
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"))
9b66ebb1 1223 (match_operand:SF 1 "s_register_operand" "0")))]
00ea1506 1224 "TARGET_32BIT && TARGET_HARD_FLOAT"
14d9aa9f 1225 "vmla%?.f32\\t%0, %2, %3"
9b66ebb1 1226 [(set_attr "predicable" "yes")
1572e697 1227 (set_attr "predicable_short_it" "no")
a8e17e9e 1228 (set_attr "type" "fmacs")]
9b66ebb1
PB
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")))]
e0dc3601 1236 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14d9aa9f 1237 "vmla%?.f64\\t%P0, %P2, %P3"
9b66ebb1 1238 [(set_attr "predicable" "yes")
1572e697 1239 (set_attr "predicable_short_it" "no")
a8e17e9e 1240 (set_attr "type" "fmacd")]
9b66ebb1
PB
1241)
1242
1243;; 0 = 1 * 2 - 0
d403b8d4
MW
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
9b66ebb1 1255(define_insn "*mulsf3subsf_vfp"
f1adb0a9
JB
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"))
9b66ebb1 1259 (match_operand:SF 1 "s_register_operand" "0")))]
00ea1506 1260 "TARGET_32BIT && TARGET_HARD_FLOAT"
14d9aa9f 1261 "vnmls%?.f32\\t%0, %2, %3"
9b66ebb1 1262 [(set_attr "predicable" "yes")
1572e697 1263 (set_attr "predicable_short_it" "no")
a8e17e9e 1264 (set_attr "type" "fmacs")]
9b66ebb1
PB
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")))]
e0dc3601 1272 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14d9aa9f 1273 "vnmls%?.f64\\t%P0, %P2, %P3"
9b66ebb1 1274 [(set_attr "predicable" "yes")
1572e697 1275 (set_attr "predicable_short_it" "no")
a8e17e9e 1276 (set_attr "type" "fmacd")]
9b66ebb1
PB
1277)
1278
1279;; 0 = -(1 * 2) + 0
d403b8d4
MW
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
9b66ebb1 1291(define_insn "*mulsf3negsfaddsf_vfp"
f1adb0a9 1292 [(set (match_operand:SF 0 "s_register_operand" "=t")
9b66ebb1 1293 (minus:SF (match_operand:SF 1 "s_register_operand" "0")
f1adb0a9
JB
1294 (mult:SF (match_operand:SF 2 "s_register_operand" "t")
1295 (match_operand:SF 3 "s_register_operand" "t"))))]
00ea1506 1296 "TARGET_32BIT && TARGET_HARD_FLOAT"
14d9aa9f 1297 "vmls%?.f32\\t%0, %2, %3"
9b66ebb1 1298 [(set_attr "predicable" "yes")
1572e697 1299 (set_attr "predicable_short_it" "no")
a8e17e9e 1300 (set_attr "type" "fmacs")]
9b66ebb1
PB
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"))))]
e0dc3601 1308 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14d9aa9f 1309 "vmls%?.f64\\t%P0, %P2, %P3"
9b66ebb1 1310 [(set_attr "predicable" "yes")
1572e697 1311 (set_attr "predicable_short_it" "no")
a8e17e9e 1312 (set_attr "type" "fmacd")]
9b66ebb1
PB
1313)
1314
1315
1316;; 0 = -(1 * 2) - 0
d403b8d4
MW
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
9b66ebb1 1329(define_insn "*mulsf3negsfsubsf_vfp"
f1adb0a9 1330 [(set (match_operand:SF 0 "s_register_operand" "=t")
9b66ebb1 1331 (minus:SF (mult:SF
f1adb0a9
JB
1332 (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
1333 (match_operand:SF 3 "s_register_operand" "t"))
9b66ebb1 1334 (match_operand:SF 1 "s_register_operand" "0")))]
00ea1506 1335 "TARGET_32BIT && TARGET_HARD_FLOAT"
14d9aa9f 1336 "vnmla%?.f32\\t%0, %2, %3"
9b66ebb1 1337 [(set_attr "predicable" "yes")
1572e697 1338 (set_attr "predicable_short_it" "no")
a8e17e9e 1339 (set_attr "type" "fmacs")]
9b66ebb1
PB
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")))]
e0dc3601 1348 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14d9aa9f 1349 "vnmla%?.f64\\t%P0, %P2, %P3"
9b66ebb1 1350 [(set_attr "predicable" "yes")
1572e697 1351 (set_attr "predicable_short_it" "no")
a8e17e9e 1352 (set_attr "type" "fmacd")]
9b66ebb1
PB
1353)
1354
76f722f4
MGD
1355;; Fused-multiply-accumulate
1356
d403b8d4
MW
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
76f722f4
MGD
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")
1572e697 1389 (set_attr "predicable_short_it" "no")
29637783 1390 (set_attr "type" "ffma<vfp_type>")]
76f722f4
MGD
1391)
1392
d403b8d4
MW
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
76f722f4
MGD
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")
1572e697 1426 (set_attr "predicable_short_it" "no")
29637783 1427 (set_attr "type" "ffma<vfp_type>")]
76f722f4
MGD
1428)
1429
d403b8d4
MW
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
76f722f4
MGD
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")
1572e697 1449 (set_attr "predicable_short_it" "no")
29637783 1450 (set_attr "type" "ffma<vfp_type>")]
76f722f4
MGD
1451)
1452
d403b8d4
MW
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
76f722f4
MGD
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")
1572e697 1473 (set_attr "predicable_short_it" "no")
29637783 1474 (set_attr "type" "ffma<vfp_type>")]
76f722f4
MGD
1475)
1476
9b66ebb1
PB
1477
1478;; Conversion routines
1479
1480(define_insn "*extendsfdf2_vfp"
1481 [(set (match_operand:DF 0 "s_register_operand" "=w")
f1adb0a9 1482 (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
e0dc3601 1483 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14a082a3 1484 "vcvt%?.f64.f32\\t%P0, %1"
9b66ebb1 1485 [(set_attr "predicable" "yes")
1572e697 1486 (set_attr "predicable_short_it" "no")
75fe7b2f 1487 (set_attr "type" "f_cvt")]
9b66ebb1
PB
1488)
1489
1490(define_insn "*truncdfsf2_vfp"
f1adb0a9 1491 [(set (match_operand:SF 0 "s_register_operand" "=t")
9b66ebb1 1492 (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
e0dc3601 1493 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14a082a3 1494 "vcvt%?.f32.f64\\t%0, %P1"
9b66ebb1 1495 [(set_attr "predicable" "yes")
1572e697 1496 (set_attr "predicable_short_it" "no")
75fe7b2f 1497 (set_attr "type" "f_cvt")]
9b66ebb1
PB
1498)
1499
0fd8c3ad
SL
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")))]
4ffc8099 1503 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
0fd8c3ad
SL
1504 "vcvtb%?.f32.f16\\t%0, %1"
1505 [(set_attr "predicable" "yes")
1572e697 1506 (set_attr "predicable_short_it" "no")
0fd8c3ad
SL
1507 (set_attr "type" "f_cvt")]
1508)
1509
5e0f10a0
JG
1510(define_insn "*truncdfhf2"
1511 [(set (match_operand:HF 0 "s_register_operand" "=t")
1512 (float_truncate:HF (match_operand:DF 1 "s_register_operand" "w")))]
1513 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1514 "vcvtb%?.f16.f64\\t%0, %P1"
1515 [(set_attr "predicable" "yes")
1516 (set_attr "predicable_short_it" "no")
1517 (set_attr "type" "f_cvt")]
1518)
1519
1520(define_insn "*extendhfdf2"
1521 [(set (match_operand:DF 0 "s_register_operand" "=w")
1522 (float_extend:DF (match_operand:HF 1 "s_register_operand" "t")))]
1523 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
1524 "vcvtb%?.f64.f16\\t%P0, %1"
1525 [(set_attr "predicable" "yes")
1526 (set_attr "predicable_short_it" "no")
1527 (set_attr "type" "f_cvt")]
1528)
1529
0fd8c3ad
SL
1530(define_insn "truncsfhf2"
1531 [(set (match_operand:HF 0 "s_register_operand" "=t")
1532 (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
4ffc8099 1533 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)"
0fd8c3ad
SL
1534 "vcvtb%?.f16.f32\\t%0, %1"
1535 [(set_attr "predicable" "yes")
1572e697 1536 (set_attr "predicable_short_it" "no")
0fd8c3ad
SL
1537 (set_attr "type" "f_cvt")]
1538)
1539
9b66ebb1 1540(define_insn "*truncsisf2_vfp"
f1adb0a9
JB
1541 [(set (match_operand:SI 0 "s_register_operand" "=t")
1542 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
00ea1506 1543 "TARGET_32BIT && TARGET_HARD_FLOAT"
14a082a3 1544 "vcvt%?.s32.f32\\t%0, %1"
9b66ebb1 1545 [(set_attr "predicable" "yes")
1572e697 1546 (set_attr "predicable_short_it" "no")
7b49c9e1 1547 (set_attr "type" "f_cvtf2i")]
9b66ebb1
PB
1548)
1549
1550(define_insn "*truncsidf2_vfp"
f1adb0a9 1551 [(set (match_operand:SI 0 "s_register_operand" "=t")
9b66ebb1 1552 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
e0dc3601 1553 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14a082a3 1554 "vcvt%?.s32.f64\\t%0, %P1"
9b66ebb1 1555 [(set_attr "predicable" "yes")
1572e697 1556 (set_attr "predicable_short_it" "no")
7b49c9e1 1557 (set_attr "type" "f_cvtf2i")]
9b66ebb1
PB
1558)
1559
6f6c1f6d
PB
1560
1561(define_insn "fixuns_truncsfsi2"
f1adb0a9
JB
1562 [(set (match_operand:SI 0 "s_register_operand" "=t")
1563 (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
00ea1506 1564 "TARGET_32BIT && TARGET_HARD_FLOAT"
14a082a3 1565 "vcvt%?.u32.f32\\t%0, %1"
6f6c1f6d 1566 [(set_attr "predicable" "yes")
1572e697 1567 (set_attr "predicable_short_it" "no")
7b49c9e1 1568 (set_attr "type" "f_cvtf2i")]
6f6c1f6d
PB
1569)
1570
1571(define_insn "fixuns_truncdfsi2"
f1adb0a9
JB
1572 [(set (match_operand:SI 0 "s_register_operand" "=t")
1573 (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
e0dc3601 1574 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14a082a3 1575 "vcvt%?.u32.f64\\t%0, %P1"
6f6c1f6d 1576 [(set_attr "predicable" "yes")
1572e697 1577 (set_attr "predicable_short_it" "no")
7b49c9e1 1578 (set_attr "type" "f_cvtf2i")]
6f6c1f6d
PB
1579)
1580
1581
9b66ebb1 1582(define_insn "*floatsisf2_vfp"
f1adb0a9
JB
1583 [(set (match_operand:SF 0 "s_register_operand" "=t")
1584 (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
00ea1506 1585 "TARGET_32BIT && TARGET_HARD_FLOAT"
14a082a3 1586 "vcvt%?.f32.s32\\t%0, %1"
9b66ebb1 1587 [(set_attr "predicable" "yes")
1572e697 1588 (set_attr "predicable_short_it" "no")
7b49c9e1 1589 (set_attr "type" "f_cvti2f")]
9b66ebb1
PB
1590)
1591
1592(define_insn "*floatsidf2_vfp"
1593 [(set (match_operand:DF 0 "s_register_operand" "=w")
f1adb0a9 1594 (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
e0dc3601 1595 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14a082a3 1596 "vcvt%?.f64.s32\\t%P0, %1"
9b66ebb1 1597 [(set_attr "predicable" "yes")
1572e697 1598 (set_attr "predicable_short_it" "no")
7b49c9e1 1599 (set_attr "type" "f_cvti2f")]
9b66ebb1
PB
1600)
1601
1602
6f6c1f6d 1603(define_insn "floatunssisf2"
f1adb0a9
JB
1604 [(set (match_operand:SF 0 "s_register_operand" "=t")
1605 (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
00ea1506 1606 "TARGET_32BIT && TARGET_HARD_FLOAT"
14a082a3 1607 "vcvt%?.f32.u32\\t%0, %1"
6f6c1f6d 1608 [(set_attr "predicable" "yes")
1572e697 1609 (set_attr "predicable_short_it" "no")
7b49c9e1 1610 (set_attr "type" "f_cvti2f")]
6f6c1f6d
PB
1611)
1612
1613(define_insn "floatunssidf2"
1614 [(set (match_operand:DF 0 "s_register_operand" "=w")
f1adb0a9 1615 (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
e0dc3601 1616 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
14a082a3 1617 "vcvt%?.f64.u32\\t%P0, %1"
6f6c1f6d 1618 [(set_attr "predicable" "yes")
1572e697 1619 (set_attr "predicable_short_it" "no")
7b49c9e1 1620 (set_attr "type" "f_cvti2f")]
6f6c1f6d
PB
1621)
1622
1623
9b66ebb1
PB
1624;; Sqrt insns.
1625
d403b8d4
MW
1626(define_insn "neon_vsqrthf"
1627 [(set (match_operand:HF 0 "s_register_operand" "=w")
1628 (sqrt:HF (match_operand:HF 1 "s_register_operand" "w")))]
1629 "TARGET_VFP_FP16INST"
1630 "vsqrt.f16\t%0, %1"
1631 [(set_attr "conds" "unconditional")
1632 (set_attr "type" "fsqrts")]
1633)
1634
1635(define_insn "neon_vrsqrtshf"
1636 [(set
1637 (match_operand:HF 0 "s_register_operand" "=w")
1638 (unspec:HF [(match_operand:HF 1 "s_register_operand" "w")
1639 (match_operand:HF 2 "s_register_operand" "w")]
1640 UNSPEC_VRSQRTS))]
1641 "TARGET_VFP_FP16INST"
1642 "vrsqrts.f16\t%0, %1, %2"
1643 [(set_attr "conds" "unconditional")
1644 (set_attr "type" "fsqrts")]
1645)
1646
a89b02c0
RE
1647; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input
1648; operands, so mark the output as early clobber for VFPv2 on ARMv5 or
1649; earlier.
9b66ebb1 1650(define_insn "*sqrtsf2_vfp"
a89b02c0
RE
1651 [(set (match_operand:SF 0 "s_register_operand" "=&t,t")
1652 (sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))]
00ea1506 1653 "TARGET_32BIT && TARGET_HARD_FLOAT"
c2786584 1654 "vsqrt%?.f32\\t%0, %1"
9b66ebb1 1655 [(set_attr "predicable" "yes")
1572e697 1656 (set_attr "predicable_short_it" "no")
a89b02c0 1657 (set_attr "arch" "*,armv6_or_vfpv3")
b86923f0 1658 (set_attr "type" "fsqrts")]
9b66ebb1
PB
1659)
1660
1661(define_insn "*sqrtdf2_vfp"
a89b02c0
RE
1662 [(set (match_operand:DF 0 "s_register_operand" "=&w,w")
1663 (sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))]
e0dc3601 1664 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
c2786584 1665 "vsqrt%?.f64\\t%P0, %P1"
9b66ebb1 1666 [(set_attr "predicable" "yes")
1572e697 1667 (set_attr "predicable_short_it" "no")
a89b02c0 1668 (set_attr "arch" "*,armv6_or_vfpv3")
b86923f0 1669 (set_attr "type" "fsqrtd")]
9b66ebb1
PB
1670)
1671
1672
1673;; Patterns to split/copy vfp condition flags.
1674
1675(define_insn "*movcc_vfp"
1676 [(set (reg CC_REGNUM)
1677 (reg VFPCC_REGNUM))]
00ea1506 1678 "TARGET_32BIT && TARGET_HARD_FLOAT"
5a150108 1679 "vmrs%?\\tAPSR_nzcv, FPSCR"
9b66ebb1 1680 [(set_attr "conds" "set")
75fe7b2f 1681 (set_attr "type" "f_flag")]
9b66ebb1
PB
1682)
1683
1684(define_insn_and_split "*cmpsf_split_vfp"
1685 [(set (reg:CCFP CC_REGNUM)
f1adb0a9
JB
1686 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t")
1687 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
00ea1506 1688 "TARGET_32BIT && TARGET_HARD_FLOAT"
9b66ebb1 1689 "#"
00ea1506 1690 "TARGET_32BIT && TARGET_HARD_FLOAT"
9b66ebb1
PB
1691 [(set (reg:CCFP VFPCC_REGNUM)
1692 (compare:CCFP (match_dup 0)
1693 (match_dup 1)))
1694 (set (reg:CCFP CC_REGNUM)
1695 (reg:CCFP VFPCC_REGNUM))]
1696 ""
1697)
1698
1699(define_insn_and_split "*cmpsf_trap_split_vfp"
1700 [(set (reg:CCFPE CC_REGNUM)
f1adb0a9
JB
1701 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t")
1702 (match_operand:SF 1 "vfp_compare_operand" "tG")))]
00ea1506 1703 "TARGET_32BIT && TARGET_HARD_FLOAT"
9b66ebb1 1704 "#"
00ea1506 1705 "TARGET_32BIT && TARGET_HARD_FLOAT"
9b66ebb1
PB
1706 [(set (reg:CCFPE VFPCC_REGNUM)
1707 (compare:CCFPE (match_dup 0)
1708 (match_dup 1)))
1709 (set (reg:CCFPE CC_REGNUM)
1710 (reg:CCFPE VFPCC_REGNUM))]
1711 ""
1712)
1713
1714(define_insn_and_split "*cmpdf_split_vfp"
1715 [(set (reg:CCFP CC_REGNUM)
1716 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
1717 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
e0dc3601 1718 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
9b66ebb1 1719 "#"
e0dc3601 1720 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
9b66ebb1
PB
1721 [(set (reg:CCFP VFPCC_REGNUM)
1722 (compare:CCFP (match_dup 0)
1723 (match_dup 1)))
1724 (set (reg:CCFP CC_REGNUM)
510bc854 1725 (reg:CCFP VFPCC_REGNUM))]
9b66ebb1
PB
1726 ""
1727)
1728
1729(define_insn_and_split "*cmpdf_trap_split_vfp"
1730 [(set (reg:CCFPE CC_REGNUM)
1731 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
1732 (match_operand:DF 1 "vfp_compare_operand" "wG")))]
e0dc3601 1733 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
9b66ebb1 1734 "#"
e0dc3601 1735 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
9b66ebb1
PB
1736 [(set (reg:CCFPE VFPCC_REGNUM)
1737 (compare:CCFPE (match_dup 0)
1738 (match_dup 1)))
1739 (set (reg:CCFPE CC_REGNUM)
1740 (reg:CCFPE VFPCC_REGNUM))]
1741 ""
1742)
1743
1744
1745;; Comparison patterns
1746
c2786584
KT
1747;; In the compare with FP zero case the ARM Architecture Reference Manual
1748;; specifies the immediate to be #0.0. However, some buggy assemblers only
1749;; accept #0. We don't want to autodetect broken assemblers, so output #0.
9b66ebb1
PB
1750(define_insn "*cmpsf_vfp"
1751 [(set (reg:CCFP VFPCC_REGNUM)
f1adb0a9
JB
1752 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t,t")
1753 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
00ea1506 1754 "TARGET_32BIT && TARGET_HARD_FLOAT"
9b66ebb1 1755 "@
c2786584
KT
1756 vcmp%?.f32\\t%0, %1
1757 vcmp%?.f32\\t%0, #0"
9b66ebb1 1758 [(set_attr "predicable" "yes")
1572e697 1759 (set_attr "predicable_short_it" "no")
51c69ddb 1760 (set_attr "type" "fcmps")]
9b66ebb1
PB
1761)
1762
1763(define_insn "*cmpsf_trap_vfp"
1764 [(set (reg:CCFPE VFPCC_REGNUM)
f1adb0a9
JB
1765 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t,t")
1766 (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
00ea1506 1767 "TARGET_32BIT && TARGET_HARD_FLOAT"
9b66ebb1 1768 "@
c2786584
KT
1769 vcmpe%?.f32\\t%0, %1
1770 vcmpe%?.f32\\t%0, #0"
9b66ebb1 1771 [(set_attr "predicable" "yes")
1572e697 1772 (set_attr "predicable_short_it" "no")
7dd8ecf0 1773 (set_attr "type" "fcmps")]
9b66ebb1
PB
1774)
1775
1776(define_insn "*cmpdf_vfp"
1777 [(set (reg:CCFP VFPCC_REGNUM)
1778 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
1779 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
e0dc3601 1780 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
9b66ebb1 1781 "@
c2786584
KT
1782 vcmp%?.f64\\t%P0, %P1
1783 vcmp%?.f64\\t%P0, #0"
9b66ebb1 1784 [(set_attr "predicable" "yes")
1572e697 1785 (set_attr "predicable_short_it" "no")
51c69ddb 1786 (set_attr "type" "fcmpd")]
9b66ebb1
PB
1787)
1788
1789(define_insn "*cmpdf_trap_vfp"
1790 [(set (reg:CCFPE VFPCC_REGNUM)
1791 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
1792 (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
e0dc3601 1793 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
9b66ebb1 1794 "@
c2786584
KT
1795 vcmpe%?.f64\\t%P0, %P1
1796 vcmpe%?.f64\\t%P0, #0"
9b66ebb1 1797 [(set_attr "predicable" "yes")
1572e697 1798 (set_attr "predicable_short_it" "no")
51c69ddb 1799 (set_attr "type" "fcmpd")]
9b66ebb1
PB
1800)
1801
d742ff4b 1802;; Fixed point to floating point conversions.
7f3d8f56
RR
1803(define_insn "*combine_vcvt_f32_<FCVTI32typename>"
1804 [(set (match_operand:SF 0 "s_register_operand" "=t")
1805 (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
d742ff4b 1806 (match_operand 2
7f3d8f56
RR
1807 "const_double_vcvt_power_of_two_reciprocal" "Dt")))]
1808 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
d742ff4b
RE
1809 "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2"
1810 [(set_attr "predicable" "yes")
1811 (set_attr "predicable_short_it" "no")
1812 (set_attr "type" "f_cvti2f")]
7f3d8f56 1813)
9b66ebb1 1814
7f3d8f56
RR
1815;; Not the ideal way of implementing this. Ideally we would be able to split
1816;; this into a move to a DP register and then a vcvt.f64.i32
1817(define_insn "*combine_vcvt_f64_<FCVTI32typename>"
1818 [(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
1819 (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
d742ff4b 1820 (match_operand 2
7f3d8f56 1821 "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
d742ff4b 1822 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
7f3d8f56
RR
1823 && !TARGET_VFP_SINGLE"
1824 "@
d742ff4b
RE
1825 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1826 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
1827 vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
1828 [(set_attr "predicable" "yes")
1829 (set_attr "ce_count" "2")
1830 (set_attr "predicable_short_it" "no")
1831 (set_attr "type" "f_cvti2f")
1832 (set_attr "length" "8")]
7f3d8f56 1833)
9b66ebb1 1834
c75d51aa 1835(define_insn "*combine_vcvtf2i"
d31e00d4
RR
1836 [(set (match_operand:SI 0 "s_register_operand" "=t")
1837 (fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0")
c75d51aa
RL
1838 (match_operand 2
1839 "const_double_vcvt_power_of_two" "Dp")))))]
1840 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
d31e00d4 1841 "vcvt%?.s32.f32\\t%0, %1, %v2"
c75d51aa
RL
1842 [(set_attr "predicable" "yes")
1843 (set_attr "predicable_short_it" "no")
d31e00d4 1844 (set_attr "type" "f_cvtf2i")]
c75d51aa
RL
1845 )
1846
d403b8d4
MW
1847;; FP16 conversions.
1848(define_insn "neon_vcvth<sup>hf"
1849 [(set (match_operand:HF 0 "s_register_operand" "=w")
1850 (unspec:HF
1851 [(match_operand:SI 1 "s_register_operand" "w")]
1852 VCVTH_US))]
1853 "TARGET_VFP_FP16INST"
1854 "vcvt.f16.<sup>%#32\t%0, %1"
1855 [(set_attr "conds" "unconditional")
1856 (set_attr "type" "f_cvti2f")]
1857)
1858
1859(define_insn "neon_vcvth<sup>si"
1860 [(set (match_operand:SI 0 "s_register_operand" "=w")
1861 (unspec:SI
1862 [(match_operand:HF 1 "s_register_operand" "w")]
1863 VCVTH_US))]
1864 "TARGET_VFP_FP16INST"
1865 "vcvt.<sup>%#32.f16\t%0, %1"
1866 [(set_attr "conds" "unconditional")
1867 (set_attr "type" "f_cvtf2i")]
1868)
1869
1870;; The neon_vcvth<sup>_nhf patterns are used to generate the instruction for the
1871;; vcvth_n_f16_<sup>32 arm_fp16 intrinsics. They are complicated by the
1872;; hardware requirement that the source and destination registers are the same
1873;; despite having different machine modes. The approach is to use a temporary
1874;; register for the conversion and move that to the correct destination.
1875
1876;; Generate an unspec pattern for the intrinsic.
1877(define_insn "neon_vcvth<sup>_nhf_unspec"
1878 [(set
1879 (match_operand:SI 0 "s_register_operand" "=w")
1880 (unspec:SI
1881 [(match_operand:SI 1 "s_register_operand" "0")
1882 (match_operand:SI 2 "immediate_operand" "i")]
1883 VCVT_HF_US_N))
1884 (set
1885 (match_operand:HF 3 "s_register_operand" "=w")
1886 (float_truncate:HF (float:SF (match_dup 0))))]
1887 "TARGET_VFP_FP16INST"
1888{
d57daa0c 1889 arm_const_bounds (operands[2], 1, 33);
d403b8d4
MW
1890 return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0";
1891}
1892 [(set_attr "conds" "unconditional")
1893 (set_attr "type" "f_cvti2f")]
1894)
1895
1896;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1897(define_expand "neon_vcvth<sup>_nhf"
1898 [(match_operand:HF 0 "s_register_operand")
1899 (unspec:HF [(match_operand:SI 1 "s_register_operand")
1900 (match_operand:SI 2 "immediate_operand")]
1901 VCVT_HF_US_N)]
1902"TARGET_VFP_FP16INST"
1903{
1904 rtx op1 = gen_reg_rtx (SImode);
1905
d57daa0c 1906 arm_const_bounds (operands[2], 1, 33);
d403b8d4
MW
1907
1908 emit_move_insn (op1, operands[1]);
1909 emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2],
1910 operands[0]));
1911 DONE;
1912})
1913
1914;; The neon_vcvth<sup>_nsi patterns are used to generate the instruction for the
1915;; vcvth_n_<sup>32_f16 arm_fp16 intrinsics. They have the same restrictions and
1916;; are implemented in the same way as the neon_vcvth<sup>_nhf patterns.
1917
1918;; Generate an unspec pattern, constraining the registers.
1919(define_insn "neon_vcvth<sup>_nsi_unspec"
1920 [(set (match_operand:SI 0 "s_register_operand" "=w")
1921 (unspec:SI
1922 [(fix:SI
1923 (fix:SF
1924 (float_extend:SF
1925 (match_operand:HF 1 "s_register_operand" "w"))))
1926 (match_operand:SI 2 "immediate_operand" "i")]
1927 VCVT_SI_US_N))]
1928 "TARGET_VFP_FP16INST"
1929{
d57daa0c 1930 arm_const_bounds (operands[2], 1, 33);
d403b8d4
MW
1931 return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2";
1932}
1933 [(set_attr "conds" "unconditional")
1934 (set_attr "type" "f_cvtf2i")]
1935)
1936
1937;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics.
1938(define_expand "neon_vcvth<sup>_nsi"
1939 [(match_operand:SI 0 "s_register_operand")
1940 (unspec:SI
1941 [(match_operand:HF 1 "s_register_operand")
1942 (match_operand:SI 2 "immediate_operand")]
1943 VCVT_SI_US_N)]
1944 "TARGET_VFP_FP16INST"
1945{
1946 rtx op1 = gen_reg_rtx (SImode);
1947
d57daa0c 1948 arm_const_bounds (operands[2], 1, 33);
d403b8d4
MW
1949 emit_insn (gen_neon_vcvth<sup>_nsi_unspec (op1, operands[1], operands[2]));
1950 emit_move_insn (operands[0], op1);
1951 DONE;
1952})
1953
1954(define_insn "neon_vcvt<vcvth_op>h<sup>si"
1955 [(set
1956 (match_operand:SI 0 "s_register_operand" "=w")
1957 (unspec:SI
1958 [(match_operand:HF 1 "s_register_operand" "w")]
1959 VCVT_HF_US))]
1960 "TARGET_VFP_FP16INST"
1961 "vcvt<vcvth_op>.<sup>%#32.f16\t%0, %1"
1962 [(set_attr "conds" "unconditional")
1963 (set_attr "type" "f_cvtf2i")]
1964)
1965
7f3d8f56 1966;; Store multiple insn used in function prologue.
9b66ebb1
PB
1967(define_insn "*push_multi_vfp"
1968 [(match_parallel 2 "multi_register_push"
1969 [(set (match_operand:BLK 0 "memory_operand" "=m")
4e6f5666 1970 (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")]
9b66ebb1 1971 UNSPEC_PUSH_MULT))])]
00ea1506 1972 "TARGET_32BIT && TARGET_HARD_FLOAT"
b27832ed 1973 "* return vfp_output_vstmd (operands);"
75fe7b2f 1974 [(set_attr "type" "f_stored")]
9b66ebb1
PB
1975)
1976
1dd4fe1f
KT
1977;; VRINT round to integral instructions.
1978;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2,
1979;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2,
1980;; rintsf2, rintdf2.
1981(define_insn "<vrint_pattern><SDF:mode>2"
1982 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
1983 (unspec:SDF [(match_operand:SDF 1
1984 "register_operand" "<F_constraint>")]
1985 VRINT))]
2f6403f1 1986 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
1dd4fe1f
KT
1987 "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
1988 [(set_attr "predicable" "<vrint_predicable>")
1572e697 1989 (set_attr "predicable_short_it" "no")
fca0efeb
KT
1990 (set_attr "type" "f_rint<vfp_type>")
1991 (set_attr "conds" "<vrint_conds>")]
1dd4fe1f 1992)
9b66ebb1 1993
ababd936
KT
1994;; Implements the lround, lfloor and lceil optabs.
1995(define_insn "l<vrint_pattern><su_optab><mode>si2"
1996 [(set (match_operand:SI 0 "register_operand" "=t")
1997 (FIXUORS:SI (unspec:SDF
1998 [(match_operand:SDF 1
1999 "register_operand" "<F_constraint>")] VCVT)))]
2000 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
962801c5 2001 "vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1"
ababd936 2002 [(set_attr "predicable" "no")
962801c5 2003 (set_attr "conds" "unconditional")
ababd936
KT
2004 (set_attr "type" "f_cvtf2i")]
2005)
2006
37202071
KT
2007;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
2008;; The 'smax' and 'smin' RTL standard pattern names do not specify which
2009;; operand will be returned when both operands are zero (i.e. they may not
2010;; honour signed zeroes), or when either operand is NaN. Therefore GCC
2011;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
2012;; NaNs.
2013
2014(define_insn "smax<mode>3"
2015 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
2016 (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
2017 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
2f6403f1 2018 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
37202071 2019 "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
fca0efeb
KT
2020 [(set_attr "type" "f_minmax<vfp_type>")
2021 (set_attr "conds" "unconditional")]
37202071
KT
2022)
2023
2024(define_insn "smin<mode>3"
2025 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>")
2026 (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>")
2027 (match_operand:SDF 2 "register_operand" "<F_constraint>")))]
2f6403f1 2028 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
37202071 2029 "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
fca0efeb
KT
2030 [(set_attr "type" "f_minmax<vfp_type>")
2031 (set_attr "conds" "unconditional")]
37202071
KT
2032)
2033
0a18c19f 2034;; Scalar forms for the IEEE-754 fmax()/fmin() functions
d403b8d4
MW
2035
2036(define_insn "neon_<fmaxmin_op>hf"
2037 [(set
2038 (match_operand:HF 0 "s_register_operand" "=w")
2039 (unspec:HF
2040 [(match_operand:HF 1 "s_register_operand" "w")
2041 (match_operand:HF 2 "s_register_operand" "w")]
2042 VMAXMINFNM))]
2043 "TARGET_VFP_FP16INST"
2044 "<fmaxmin_op>.f16\t%0, %1, %2"
2045 [(set_attr "conds" "unconditional")
2046 (set_attr "type" "f_minmaxs")]
2047)
2048
0a18c19f
DS
2049(define_insn "<fmaxmin><mode>3"
2050 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
2051 (unspec:SDF [(match_operand:SDF 1 "s_register_operand" "<F_constraint>")
2052 (match_operand:SDF 2 "s_register_operand" "<F_constraint>")]
2053 VMAXMINFNM))]
2054 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
2055 "<fmaxmin_op>.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2056 [(set_attr "type" "f_minmax<vfp_type>")
2057 (set_attr "conds" "unconditional")]
2058)
2059
f10743d3
KV
2060;; Write Floating-point Status and Control Register.
2061(define_insn "set_fpscr"
2062 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)]
00ea1506 2063 "TARGET_HARD_FLOAT"
f10743d3
KV
2064 "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
2065 [(set_attr "type" "mrs")])
2066
2067;; Read Floating-point Status and Control Register.
2068(define_insn "get_fpscr"
2069 [(set (match_operand:SI 0 "register_operand" "=r")
2070 (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
00ea1506 2071 "TARGET_HARD_FLOAT"
f10743d3
KV
2072 "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
2073 [(set_attr "type" "mrs")])
2074
2075
9b66ebb1
PB
2076;; Unimplemented insns:
2077;; fldm*
2078;; fstm*
2079;; fmdhr et al (VFPv1)
59b9a953 2080;; Support for xD (single precision only) variants.
9b66ebb1 2081;; fmrrs, fmsrr
655b5fc8
AV
2082
2083;; Split an immediate DF move to two immediate SI moves.
2084(define_insn_and_split "no_literal_pool_df_immediate"
2085 [(set (match_operand:DF 0 "s_register_operand" "")
2086 (match_operand:DF 1 "const_double_operand" ""))]
2087 "TARGET_THUMB2 && arm_disable_literal_pool
2088 && !(TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
2089 && vfp3_const_double_rtx (operands[1]))"
2090 "#"
2091 "&& !reload_completed"
2092 [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
2093 (set (subreg:SI (match_dup 1) 4) (match_dup 3))
2094 (set (match_dup 0) (match_dup 1))]
2095 "
2096 long buf[2];
2097 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
2098 operands[2] = GEN_INT ((int) buf[0]);
2099 operands[3] = GEN_INT ((int) buf[1]);
2100 operands[1] = gen_reg_rtx (DFmode);
2101 ")
2102
2103;; Split an immediate SF move to one immediate SI move.
2104(define_insn_and_split "no_literal_pool_sf_immediate"
2105 [(set (match_operand:SF 0 "s_register_operand" "")
2106 (match_operand:SF 1 "const_double_operand" ""))]
2107 "TARGET_THUMB2 && arm_disable_literal_pool
2108 && !(TARGET_HARD_FLOAT && vfp3_const_double_rtx (operands[1]))"
2109 "#"
2110 "&& !reload_completed"
2111 [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
2112 (set (match_dup 0) (match_dup 1))]
2113 "
2114 long buf;
2115 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
2116 operands[2] = GEN_INT ((int) buf);
2117 operands[1] = gen_reg_rtx (SFmode);
2118 ")