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