]>
Commit | Line | Data |
---|---|---|
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 | ") |