]>
Commit | Line | Data |
---|---|---|
3f4d9b98 | 1 | ;; ARM VFP instruction patterns |
5624e564 | 2 | ;; Copyright (C) 2003-2015 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 | |
9b66ebb1 PB |
21 | ;; SImode moves |
22 | ;; ??? For now do not allow loading constants into vfp regs. This causes | |
59b9a953 | 23 | ;; problems because small constants get converted into adds. |
9b66ebb1 | 24 | (define_insn "*arm_movsi_vfp" |
f5c630c3 | 25 | [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv") |
d58bc084 | 26 | (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk,r,*t,*t,*Uvi,*t"))] |
9b66ebb1 PB |
27 | "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT |
28 | && ( s_register_operand (operands[0], SImode) | |
29 | || s_register_operand (operands[1], SImode))" | |
5b3e6663 PB |
30 | "* |
31 | switch (which_alternative) | |
32 | { | |
f5c630c3 | 33 | case 0: case 1: |
5b3e6663 | 34 | return \"mov%?\\t%0, %1\"; |
5b3e6663 | 35 | case 2: |
f5c630c3 | 36 | return \"mvn%?\\t%0, #%B1\"; |
5b3e6663 | 37 | case 3: |
f5c630c3 | 38 | return \"movw%?\\t%0, %1\"; |
5b3e6663 | 39 | case 4: |
f5c630c3 | 40 | return \"ldr%?\\t%0, %1\"; |
5b3e6663 | 41 | case 5: |
f5c630c3 | 42 | return \"str%?\\t%1, %0\"; |
5b3e6663 | 43 | case 6: |
35cb3e53 | 44 | return \"vmov%?\\t%0, %1\\t%@ int\"; |
5b3e6663 | 45 | case 7: |
35cb3e53 | 46 | return \"vmov%?\\t%0, %1\\t%@ int\"; |
f5c630c3 | 47 | case 8: |
35cb3e53 | 48 | return \"vmov%?.f32\\t%0, %1\\t%@ int\"; |
f5c630c3 | 49 | case 9: case 10: |
5b3e6663 PB |
50 | return output_move_vfp (operands); |
51 | default: | |
52 | gcc_unreachable (); | |
53 | } | |
54 | " | |
55 | [(set_attr "predicable" "yes") | |
292b89b3 | 56 | (set_attr "type" "mov_reg,mov_reg,mvn_imm,mov_imm,load1,store1,f_mcr,f_mrc,fmov,f_loads,f_stores") |
f5c630c3 PB |
57 | (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*") |
58 | (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")] | |
5b3e6663 PB |
59 | ) |
60 | ||
28907f9a MS |
61 | ;; See thumb2.md:thumb2_movsi_insn for an explanation of the split |
62 | ;; high/low register alternatives for loads and stores here. | |
956a95a5 KT |
63 | ;; The l/Py alternative should come after r/I to ensure that the short variant |
64 | ;; is chosen with length 2 when the instruction is predicated for | |
65 | ;; arm_restrict_it. | |
5b3e6663 | 66 | (define_insn "*thumb2_movsi_vfp" |
956a95a5 KT |
67 | [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r, l,*hk,m, *m,*t, r,*t,*t, *Uv") |
68 | (match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,*mi,l,*hk, r,*t,*t,*Uvi,*t"))] | |
5b3e6663 PB |
69 | "TARGET_THUMB2 && TARGET_VFP && TARGET_HARD_FLOAT |
70 | && ( s_register_operand (operands[0], SImode) | |
71 | || s_register_operand (operands[1], SImode))" | |
72 | "* | |
73 | switch (which_alternative) | |
74 | { | |
956a95a5 KT |
75 | case 0: |
76 | case 1: | |
5b3e6663 | 77 | case 2: |
956a95a5 | 78 | return \"mov%?\\t%0, %1\"; |
5b3e6663 | 79 | case 3: |
956a95a5 | 80 | return \"mvn%?\\t%0, #%B1\"; |
5b3e6663 | 81 | case 4: |
956a95a5 | 82 | return \"movw%?\\t%0, %1\"; |
5b3e6663 | 83 | case 5: |
5b3e6663 | 84 | case 6: |
956a95a5 | 85 | return \"ldr%?\\t%0, %1\"; |
5b3e6663 | 86 | case 7: |
f5c630c3 | 87 | case 8: |
956a95a5 | 88 | return \"str%?\\t%1, %0\"; |
28907f9a | 89 | case 9: |
35cb3e53 | 90 | return \"vmov%?\\t%0, %1\\t%@ int\"; |
28907f9a | 91 | case 10: |
35cb3e53 | 92 | return \"vmov%?\\t%0, %1\\t%@ int\"; |
956a95a5 | 93 | case 11: |
35cb3e53 | 94 | return \"vmov%?.f32\\t%0, %1\\t%@ int\"; |
956a95a5 | 95 | case 12: case 13: |
5b3e6663 PB |
96 | return output_move_vfp (operands); |
97 | default: | |
98 | gcc_unreachable (); | |
99 | } | |
100 | " | |
9b66ebb1 | 101 | [(set_attr "predicable" "yes") |
956a95a5 | 102 | (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no") |
56912037 | 103 | (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 | 104 | (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4") |
956a95a5 KT |
105 | (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*") |
106 | (set_attr "neg_pool_range" "*,*,*,*,*, 0, 0,*,*,*,*,*,1008,*")] | |
9b66ebb1 PB |
107 | ) |
108 | ||
109 | ||
110 | ;; DImode moves | |
111 | ||
0127c76f | 112 | (define_insn "*movdi_vfp" |
4542a38a GY |
113 | [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,q,q,m,w,r,w,w, Uv") |
114 | (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,q,r,w,w,Uvi,w"))] | |
0127c76f | 115 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune != cortexa8 |
7baa7c13 | 116 | && ( register_operand (operands[0], DImode) |
00a3a76a AS |
117 | || register_operand (operands[1], DImode)) |
118 | && !(TARGET_NEON && CONST_INT_P (operands[1]) | |
119 | && neon_immediate_valid_for_move (operands[1], DImode, NULL, NULL))" | |
7baa7c13 BS |
120 | "* |
121 | switch (which_alternative) | |
122 | { | |
123 | case 0: | |
7baa7c13 BS |
124 | case 1: |
125 | case 2: | |
7baa7c13 | 126 | case 3: |
0127c76f | 127 | return \"#\"; |
7baa7c13 | 128 | case 4: |
7baa7c13 | 129 | case 5: |
0127c76f | 130 | case 6: |
3598da80 | 131 | return output_move_double (operands, true, NULL); |
0127c76f | 132 | case 7: |
35cb3e53 | 133 | return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\"; |
0127c76f | 134 | case 8: |
35cb3e53 | 135 | return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\"; |
0127c76f | 136 | case 9: |
7baa7c13 | 137 | if (TARGET_VFP_SINGLE) |
35cb3e53 | 138 | return \"vmov%?.f32\\t%0, %1\\t%@ int\;vmov%?.f32\\t%p0, %p1\\t%@ int\"; |
7baa7c13 | 139 | else |
35cb3e53 | 140 | return \"vmov%?.f64\\t%P0, %P1\\t%@ int\"; |
0127c76f | 141 | case 10: case 11: |
7baa7c13 BS |
142 | return output_move_vfp (operands); |
143 | default: | |
144 | gcc_unreachable (); | |
145 | } | |
146 | " | |
594726e4 | 147 | [(set_attr "type" "multiple,multiple,multiple,multiple,load2,load2,store2,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored") |
0127c76f RR |
148 | (set (attr "length") (cond [(eq_attr "alternative" "1,4,5,6") (const_int 8) |
149 | (eq_attr "alternative" "2") (const_int 12) | |
150 | (eq_attr "alternative" "3") (const_int 16) | |
151 | (eq_attr "alternative" "9") | |
152 | (if_then_else | |
b75b1be2 | 153 | (match_test "TARGET_VFP_SINGLE") |
0127c76f RR |
154 | (const_int 8) |
155 | (const_int 4))] | |
156 | (const_int 4))) | |
88f519b2 MGD |
157 | (set_attr "arm_pool_range" "*,*,*,*,1020,4096,*,*,*,*,1020,*") |
158 | (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*") | |
635a48fb | 159 | (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*") |
0127c76f | 160 | (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")] |
7baa7c13 BS |
161 | ) |
162 | ||
0127c76f RR |
163 | (define_insn "*movdi_vfp_cortexa8" |
164 | [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,r,r,m,w,!r,w,w, Uv") | |
165 | (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,r,r,w,w,Uvi,w"))] | |
166 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune == cortexa8 | |
167 | && ( register_operand (operands[0], DImode) | |
00a3a76a AS |
168 | || register_operand (operands[1], DImode)) |
169 | && !(TARGET_NEON && CONST_INT_P (operands[1]) | |
170 | && neon_immediate_valid_for_move (operands[1], DImode, NULL, NULL))" | |
9b66ebb1 PB |
171 | "* |
172 | switch (which_alternative) | |
173 | { | |
9b901d50 | 174 | case 0: |
9b901d50 RE |
175 | case 1: |
176 | case 2: | |
9b66ebb1 | 177 | case 3: |
0127c76f | 178 | return \"#\"; |
9b66ebb1 | 179 | case 4: |
9b66ebb1 | 180 | case 5: |
0127c76f | 181 | case 6: |
3598da80 | 182 | return output_move_double (operands, true, NULL); |
0127c76f | 183 | case 7: |
35cb3e53 | 184 | return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\"; |
0127c76f | 185 | case 8: |
35cb3e53 | 186 | return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\"; |
0127c76f | 187 | case 9: |
35cb3e53 | 188 | return \"vmov%?.f64\\t%P0, %P1\\t%@ int\"; |
0127c76f | 189 | case 10: case 11: |
5b3e6663 PB |
190 | return output_move_vfp (operands); |
191 | default: | |
0127c76f | 192 | gcc_unreachable (); |
5b3e6663 PB |
193 | } |
194 | " | |
594726e4 | 195 | [(set_attr "type" "multiple,multiple,multiple,multiple,load2,load2,store2,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored") |
3598da80 RR |
196 | (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8) |
197 | (eq_attr "alternative" "2") (const_int 12) | |
198 | (eq_attr "alternative" "3") (const_int 16) | |
199 | (eq_attr "alternative" "4,5,6") | |
200 | (symbol_ref | |
201 | "arm_count_output_move_double_insns (operands) \ | |
202 | * 4")] | |
203 | (const_int 4))) | |
0127c76f | 204 | (set_attr "predicable" "yes") |
88f519b2 MGD |
205 | (set_attr "arm_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*") |
206 | (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*") | |
635a48fb | 207 | (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*") |
3598da80 RR |
208 | (set (attr "ce_count") |
209 | (symbol_ref "get_attr_length (insn) / 4")) | |
0127c76f RR |
210 | (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")] |
211 | ) | |
5b3e6663 | 212 | |
0fd8c3ad | 213 | ;; HFmode moves |
e0dc3601 | 214 | (define_insn "*movhf_vfp_neon" |
0fd8c3ad SL |
215 | [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r") |
216 | (match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))] | |
217 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_NEON_FP16 | |
218 | && ( s_register_operand (operands[0], HFmode) | |
219 | || s_register_operand (operands[1], HFmode))" | |
220 | "* | |
221 | switch (which_alternative) | |
222 | { | |
223 | case 0: /* S register from memory */ | |
224 | return \"vld1.16\\t{%z0}, %A1\"; | |
225 | case 1: /* memory from S register */ | |
226 | return \"vst1.16\\t{%z1}, %A0\"; | |
227 | case 2: /* ARM register from memory */ | |
228 | return \"ldrh\\t%0, %1\\t%@ __fp16\"; | |
229 | case 3: /* memory from ARM register */ | |
230 | return \"strh\\t%1, %0\\t%@ __fp16\"; | |
231 | case 4: /* S register from S register */ | |
35cb3e53 | 232 | return \"vmov.f32\\t%0, %1\"; |
0fd8c3ad SL |
233 | case 5: /* ARM register from ARM register */ |
234 | return \"mov\\t%0, %1\\t%@ __fp16\"; | |
235 | case 6: /* S register from ARM register */ | |
35cb3e53 | 236 | return \"vmov\\t%0, %1\"; |
0fd8c3ad | 237 | case 7: /* ARM register from S register */ |
35cb3e53 | 238 | return \"vmov\\t%0, %1\"; |
0fd8c3ad SL |
239 | case 8: /* ARM register from constant */ |
240 | { | |
0fd8c3ad SL |
241 | long bits; |
242 | rtx ops[4]; | |
243 | ||
34a72c33 RS |
244 | bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), |
245 | HFmode); | |
0fd8c3ad SL |
246 | ops[0] = operands[0]; |
247 | ops[1] = GEN_INT (bits); | |
248 | ops[2] = GEN_INT (bits & 0xff00); | |
249 | ops[3] = GEN_INT (bits & 0x00ff); | |
250 | ||
251 | if (arm_arch_thumb2) | |
252 | output_asm_insn (\"movw\\t%0, %1\", ops); | |
253 | else | |
254 | output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops); | |
255 | return \"\"; | |
256 | } | |
257 | default: | |
258 | gcc_unreachable (); | |
259 | } | |
260 | " | |
261 | [(set_attr "conds" "unconditional") | |
f7379e5e | 262 | (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\ |
292b89b3 | 263 | load1,store1,fmov,mov_reg,f_mcr,f_mrc,multiple") |
0fd8c3ad SL |
264 | (set_attr "length" "4,4,4,4,4,4,4,4,8")] |
265 | ) | |
266 | ||
e0dc3601 PB |
267 | ;; FP16 without element load/store instructions. |
268 | (define_insn "*movhf_vfp" | |
269 | [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r") | |
270 | (match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))] | |
271 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16 && !TARGET_NEON_FP16 | |
272 | && ( s_register_operand (operands[0], HFmode) | |
273 | || s_register_operand (operands[1], HFmode))" | |
274 | "* | |
275 | switch (which_alternative) | |
276 | { | |
277 | case 0: /* ARM register from memory */ | |
278 | return \"ldrh\\t%0, %1\\t%@ __fp16\"; | |
279 | case 1: /* memory from ARM register */ | |
280 | return \"strh\\t%1, %0\\t%@ __fp16\"; | |
281 | case 2: /* S register from S register */ | |
35cb3e53 | 282 | return \"vmov.f32\\t%0, %1\"; |
e0dc3601 PB |
283 | case 3: /* ARM register from ARM register */ |
284 | return \"mov\\t%0, %1\\t%@ __fp16\"; | |
285 | case 4: /* S register from ARM register */ | |
35cb3e53 | 286 | return \"vmov\\t%0, %1\"; |
e0dc3601 | 287 | case 5: /* ARM register from S register */ |
35cb3e53 | 288 | return \"vmov\\t%0, %1\"; |
e0dc3601 PB |
289 | case 6: /* ARM register from constant */ |
290 | { | |
e0dc3601 PB |
291 | long bits; |
292 | rtx ops[4]; | |
293 | ||
34a72c33 RS |
294 | bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), |
295 | HFmode); | |
e0dc3601 PB |
296 | ops[0] = operands[0]; |
297 | ops[1] = GEN_INT (bits); | |
298 | ops[2] = GEN_INT (bits & 0xff00); | |
299 | ops[3] = GEN_INT (bits & 0x00ff); | |
300 | ||
301 | if (arm_arch_thumb2) | |
302 | output_asm_insn (\"movw\\t%0, %1\", ops); | |
303 | else | |
304 | output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops); | |
305 | return \"\"; | |
306 | } | |
307 | default: | |
308 | gcc_unreachable (); | |
309 | } | |
310 | " | |
311 | [(set_attr "conds" "unconditional") | |
292b89b3 | 312 | (set_attr "type" "load1,store1,fmov,mov_reg,f_mcr,f_mrc,multiple") |
e0dc3601 PB |
313 | (set_attr "length" "4,4,4,4,4,4,8")] |
314 | ) | |
315 | ||
9b66ebb1 PB |
316 | |
317 | ;; SFmode moves | |
221b2a64 PB |
318 | ;; Disparage the w<->r cases because reloading an invalid address is |
319 | ;; preferable to loading the value via integer registers. | |
9b66ebb1 PB |
320 | |
321 | (define_insn "*movsf_vfp" | |
f1adb0a9 | 322 | [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t ,Uv,r ,m,t,r") |
35cb3e53 | 323 | (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))] |
9b66ebb1 PB |
324 | "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP |
325 | && ( s_register_operand (operands[0], SFmode) | |
326 | || s_register_operand (operands[1], SFmode))" | |
5b3e6663 PB |
327 | "* |
328 | switch (which_alternative) | |
329 | { | |
330 | case 0: | |
35cb3e53 | 331 | return \"vmov%?\\t%0, %1\"; |
5b3e6663 | 332 | case 1: |
35cb3e53 | 333 | return \"vmov%?\\t%0, %1\"; |
f1adb0a9 | 334 | case 2: |
35cb3e53 | 335 | return \"vmov%?.f32\\t%0, %1\"; |
f1adb0a9 | 336 | case 3: case 4: |
5b3e6663 | 337 | return output_move_vfp (operands); |
5b3e6663 | 338 | case 5: |
f1adb0a9 | 339 | return \"ldr%?\\t%0, %1\\t%@ float\"; |
5b3e6663 | 340 | case 6: |
f1adb0a9 | 341 | return \"str%?\\t%1, %0\\t%@ float\"; |
5b3e6663 | 342 | case 7: |
35cb3e53 | 343 | return \"vmov%?.f32\\t%0, %1\"; |
f1adb0a9 | 344 | case 8: |
5b3e6663 PB |
345 | return \"mov%?\\t%0, %1\\t%@ float\"; |
346 | default: | |
347 | gcc_unreachable (); | |
348 | } | |
349 | " | |
9b66ebb1 | 350 | [(set_attr "predicable" "yes") |
f1adb0a9 | 351 | (set_attr "type" |
292b89b3 | 352 | "f_mcr,f_mrc,fconsts,f_loads,f_stores,load1,store1,fmov,mov_reg") |
f1adb0a9 JB |
353 | (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*") |
354 | (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")] | |
9b66ebb1 PB |
355 | ) |
356 | ||
5b3e6663 | 357 | (define_insn "*thumb2_movsf_vfp" |
f1adb0a9 JB |
358 | [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t ,Uv,r ,m,t,r") |
359 | (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))] | |
5b3e6663 PB |
360 | "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP |
361 | && ( s_register_operand (operands[0], SFmode) | |
362 | || s_register_operand (operands[1], SFmode))" | |
363 | "* | |
364 | switch (which_alternative) | |
365 | { | |
366 | case 0: | |
35cb3e53 | 367 | return \"vmov%?\\t%0, %1\"; |
5b3e6663 | 368 | case 1: |
35cb3e53 | 369 | return \"vmov%?\\t%0, %1\"; |
f1adb0a9 | 370 | case 2: |
35cb3e53 | 371 | return \"vmov%?.f32\\t%0, %1\"; |
f1adb0a9 | 372 | case 3: case 4: |
5b3e6663 | 373 | return output_move_vfp (operands); |
5b3e6663 | 374 | case 5: |
f1adb0a9 | 375 | return \"ldr%?\\t%0, %1\\t%@ float\"; |
5b3e6663 | 376 | case 6: |
f1adb0a9 | 377 | return \"str%?\\t%1, %0\\t%@ float\"; |
5b3e6663 | 378 | case 7: |
35cb3e53 | 379 | return \"vmov%?.f32\\t%0, %1\"; |
f1adb0a9 | 380 | case 8: |
5b3e6663 PB |
381 | return \"mov%?\\t%0, %1\\t%@ float\"; |
382 | default: | |
383 | gcc_unreachable (); | |
384 | } | |
385 | " | |
386 | [(set_attr "predicable" "yes") | |
1572e697 | 387 | (set_attr "predicable_short_it" "no") |
f1adb0a9 | 388 | (set_attr "type" |
292b89b3 | 389 | "f_mcr,f_mrc,fconsts,f_loads,f_stores,load1,store1,fmov,mov_reg") |
88f519b2 | 390 | (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*") |
f1adb0a9 | 391 | (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")] |
5b3e6663 PB |
392 | ) |
393 | ||
9b66ebb1 PB |
394 | ;; DFmode moves |
395 | ||
396 | (define_insn "*movdf_vfp" | |
95f89bb3 RR |
397 | [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w ,Uv,r, m,w,r") |
398 | (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,UvF,w ,mF,r,w,r"))] | |
d5b6e637 PB |
399 | "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP |
400 | && ( register_operand (operands[0], DFmode) | |
401 | || register_operand (operands[1], DFmode))" | |
9b66ebb1 PB |
402 | "* |
403 | { | |
404 | switch (which_alternative) | |
405 | { | |
406 | case 0: | |
35cb3e53 | 407 | return \"vmov%?\\t%P0, %Q1, %R1\"; |
9b66ebb1 | 408 | case 1: |
35cb3e53 | 409 | return \"vmov%?\\t%Q0, %R0, %P1\"; |
f1adb0a9 | 410 | case 2: |
e0dc3601 | 411 | gcc_assert (TARGET_VFP_DOUBLE); |
35cb3e53 | 412 | return \"vmov%?.f64\\t%P0, %1\"; |
f1adb0a9 | 413 | case 3: case 4: |
5b3e6663 | 414 | return output_move_vfp (operands); |
95f89bb3 | 415 | case 5: case 6: |
3598da80 | 416 | return output_move_double (operands, true, NULL); |
9b901d50 | 417 | case 7: |
e0dc3601 | 418 | if (TARGET_VFP_SINGLE) |
35cb3e53 | 419 | return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\"; |
e0dc3601 | 420 | else |
35cb3e53 | 421 | return \"vmov%?.f64\\t%P0, %P1\"; |
f1adb0a9 | 422 | case 8: |
9b901d50 | 423 | return \"#\"; |
9b66ebb1 | 424 | default: |
e6d29d15 | 425 | gcc_unreachable (); |
9b66ebb1 PB |
426 | } |
427 | } | |
428 | " | |
003bb7f3 | 429 | [(set_attr "type" "f_mcrr,f_mrrc,fconstd,f_loadd,f_stored,\ |
594726e4 | 430 | load2,store2,ffarithd,multiple") |
95f89bb3 | 431 | (set (attr "length") (cond [(eq_attr "alternative" "5,6,8") (const_int 8) |
e0dc3601 PB |
432 | (eq_attr "alternative" "7") |
433 | (if_then_else | |
b75b1be2 | 434 | (match_test "TARGET_VFP_SINGLE") |
e0dc3601 PB |
435 | (const_int 8) |
436 | (const_int 4))] | |
437 | (const_int 4))) | |
54f52b81 | 438 | (set_attr "predicable" "yes") |
f1adb0a9 | 439 | (set_attr "pool_range" "*,*,*,1020,*,1020,*,*,*") |
635a48fb | 440 | (set_attr "neg_pool_range" "*,*,*,1004,*,1004,*,*,*")] |
9b66ebb1 PB |
441 | ) |
442 | ||
5b3e6663 | 443 | (define_insn "*thumb2_movdf_vfp" |
95f89bb3 RR |
444 | [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w ,Uv,r ,m,w,r") |
445 | (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,UvF,w, mF,r, w,r"))] | |
de7c74be RB |
446 | "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP |
447 | && ( register_operand (operands[0], DFmode) | |
448 | || register_operand (operands[1], DFmode))" | |
5b3e6663 PB |
449 | "* |
450 | { | |
451 | switch (which_alternative) | |
452 | { | |
453 | case 0: | |
35cb3e53 | 454 | return \"vmov%?\\t%P0, %Q1, %R1\"; |
5b3e6663 | 455 | case 1: |
35cb3e53 | 456 | return \"vmov%?\\t%Q0, %R0, %P1\"; |
f1adb0a9 | 457 | case 2: |
e0dc3601 | 458 | gcc_assert (TARGET_VFP_DOUBLE); |
35cb3e53 | 459 | return \"vmov%?.f64\\t%P0, %1\"; |
95f89bb3 | 460 | case 3: case 4: |
5b3e6663 | 461 | return output_move_vfp (operands); |
95f89bb3 | 462 | case 5: case 6: case 8: |
3598da80 | 463 | return output_move_double (operands, true, NULL); |
f1adb0a9 | 464 | case 7: |
e0dc3601 | 465 | if (TARGET_VFP_SINGLE) |
35cb3e53 | 466 | return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\"; |
e0dc3601 | 467 | else |
35cb3e53 | 468 | return \"vmov%?.f64\\t%P0, %P1\"; |
5b3e6663 PB |
469 | default: |
470 | abort (); | |
471 | } | |
472 | } | |
473 | " | |
003bb7f3 | 474 | [(set_attr "type" "f_mcrr,f_mrrc,fconstd,f_loadd,\ |
594726e4 | 475 | f_stored,load2,store2,ffarithd,multiple") |
95f89bb3 | 476 | (set (attr "length") (cond [(eq_attr "alternative" "5,6,8") (const_int 8) |
e0dc3601 PB |
477 | (eq_attr "alternative" "7") |
478 | (if_then_else | |
b75b1be2 | 479 | (match_test "TARGET_VFP_SINGLE") |
e0dc3601 PB |
480 | (const_int 8) |
481 | (const_int 4))] | |
482 | (const_int 4))) | |
88f519b2 | 483 | (set_attr "pool_range" "*,*,*,1018,*,4094,*,*,*") |
95f89bb3 | 484 | (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")] |
5b3e6663 PB |
485 | ) |
486 | ||
9b66ebb1 PB |
487 | |
488 | ;; Conditional move patterns | |
489 | ||
490 | (define_insn "*movsfcc_vfp" | |
f1adb0a9 | 491 | [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r") |
9b66ebb1 PB |
492 | (if_then_else:SF |
493 | (match_operator 3 "arm_comparison_operator" | |
494 | [(match_operand 4 "cc_register" "") (const_int 0)]) | |
f1adb0a9 JB |
495 | (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t") |
496 | (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))] | |
9b66ebb1 PB |
497 | "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP" |
498 | "@ | |
35cb3e53 KT |
499 | vmov%D3.f32\\t%0, %2 |
500 | vmov%d3.f32\\t%0, %1 | |
501 | vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1 | |
502 | vmov%D3\\t%0, %2 | |
503 | vmov%d3\\t%0, %1 | |
504 | vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1 | |
505 | vmov%D3\\t%0, %2 | |
506 | vmov%d3\\t%0, %1 | |
507 | vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1" | |
9b66ebb1 PB |
508 | [(set_attr "conds" "use") |
509 | (set_attr "length" "4,4,8,4,4,8,4,4,8") | |
292b89b3 | 510 | (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")] |
9b66ebb1 PB |
511 | ) |
512 | ||
5b3e6663 | 513 | (define_insn "*thumb2_movsfcc_vfp" |
f1adb0a9 | 514 | [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r") |
5b3e6663 PB |
515 | (if_then_else:SF |
516 | (match_operator 3 "arm_comparison_operator" | |
517 | [(match_operand 4 "cc_register" "") (const_int 0)]) | |
f1adb0a9 JB |
518 | (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t") |
519 | (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))] | |
1572e697 | 520 | "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP && !arm_restrict_it" |
5b3e6663 | 521 | "@ |
35cb3e53 KT |
522 | it\\t%D3\;vmov%D3.f32\\t%0, %2 |
523 | it\\t%d3\;vmov%d3.f32\\t%0, %1 | |
524 | ite\\t%D3\;vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1 | |
525 | it\\t%D3\;vmov%D3\\t%0, %2 | |
526 | it\\t%d3\;vmov%d3\\t%0, %1 | |
527 | ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1 | |
528 | it\\t%D3\;vmov%D3\\t%0, %2 | |
529 | it\\t%d3\;vmov%d3\\t%0, %1 | |
530 | ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1" | |
5b3e6663 PB |
531 | [(set_attr "conds" "use") |
532 | (set_attr "length" "6,6,10,6,6,10,6,6,10") | |
292b89b3 | 533 | (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")] |
5b3e6663 PB |
534 | ) |
535 | ||
9b66ebb1 PB |
536 | (define_insn "*movdfcc_vfp" |
537 | [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r") | |
538 | (if_then_else:DF | |
539 | (match_operator 3 "arm_comparison_operator" | |
540 | [(match_operand 4 "cc_register" "") (const_int 0)]) | |
541 | (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w") | |
542 | (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))] | |
e0dc3601 | 543 | "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
9b66ebb1 | 544 | "@ |
35cb3e53 KT |
545 | vmov%D3.f64\\t%P0, %P2 |
546 | vmov%d3.f64\\t%P0, %P1 | |
547 | vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1 | |
548 | vmov%D3\\t%P0, %Q2, %R2 | |
549 | vmov%d3\\t%P0, %Q1, %R1 | |
550 | vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1 | |
551 | vmov%D3\\t%Q0, %R0, %P2 | |
552 | vmov%d3\\t%Q0, %R0, %P1 | |
553 | vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1" | |
9b66ebb1 PB |
554 | [(set_attr "conds" "use") |
555 | (set_attr "length" "4,4,8,4,4,8,4,4,8") | |
003bb7f3 | 556 | (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcr,f_mrrc,f_mrrc,f_mrrc")] |
9b66ebb1 PB |
557 | ) |
558 | ||
5b3e6663 PB |
559 | (define_insn "*thumb2_movdfcc_vfp" |
560 | [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r") | |
561 | (if_then_else:DF | |
562 | (match_operator 3 "arm_comparison_operator" | |
563 | [(match_operand 4 "cc_register" "") (const_int 0)]) | |
564 | (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w") | |
565 | (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))] | |
1572e697 | 566 | "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && !arm_restrict_it" |
5b3e6663 | 567 | "@ |
35cb3e53 KT |
568 | it\\t%D3\;vmov%D3.f64\\t%P0, %P2 |
569 | it\\t%d3\;vmov%d3.f64\\t%P0, %P1 | |
570 | ite\\t%D3\;vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1 | |
571 | it\t%D3\;vmov%D3\\t%P0, %Q2, %R2 | |
572 | it\t%d3\;vmov%d3\\t%P0, %Q1, %R1 | |
573 | ite\\t%D3\;vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1 | |
574 | it\t%D3\;vmov%D3\\t%Q0, %R0, %P2 | |
575 | it\t%d3\;vmov%d3\\t%Q0, %R0, %P1 | |
576 | ite\\t%D3\;vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1" | |
5b3e6663 PB |
577 | [(set_attr "conds" "use") |
578 | (set_attr "length" "6,6,10,6,6,10,6,6,10") | |
594726e4 | 579 | (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcrr,f_mrrc,f_mrrc,f_mrrc")] |
5b3e6663 PB |
580 | ) |
581 | ||
9b66ebb1 PB |
582 | |
583 | ;; Sign manipulation functions | |
584 | ||
585 | (define_insn "*abssf2_vfp" | |
f1adb0a9 JB |
586 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
587 | (abs:SF (match_operand:SF 1 "s_register_operand" "t")))] | |
5b3e6663 | 588 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
436c249d | 589 | "vabs%?.f32\\t%0, %1" |
9b66ebb1 | 590 | [(set_attr "predicable" "yes") |
1572e697 | 591 | (set_attr "predicable_short_it" "no") |
51c69ddb | 592 | (set_attr "type" "ffariths")] |
9b66ebb1 PB |
593 | ) |
594 | ||
595 | (define_insn "*absdf2_vfp" | |
596 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
597 | (abs:DF (match_operand:DF 1 "s_register_operand" "w")))] | |
e0dc3601 | 598 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
436c249d | 599 | "vabs%?.f64\\t%P0, %P1" |
9b66ebb1 | 600 | [(set_attr "predicable" "yes") |
1572e697 | 601 | (set_attr "predicable_short_it" "no") |
51c69ddb | 602 | (set_attr "type" "ffarithd")] |
9b66ebb1 PB |
603 | ) |
604 | ||
605 | (define_insn "*negsf2_vfp" | |
f1adb0a9 JB |
606 | [(set (match_operand:SF 0 "s_register_operand" "=t,?r") |
607 | (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))] | |
5b3e6663 | 608 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
81632f11 | 609 | "@ |
436c249d | 610 | vneg%?.f32\\t%0, %1 |
81632f11 | 611 | eor%?\\t%0, %1, #-2147483648" |
9b66ebb1 | 612 | [(set_attr "predicable" "yes") |
1572e697 | 613 | (set_attr "predicable_short_it" "no") |
51c69ddb | 614 | (set_attr "type" "ffariths")] |
9b66ebb1 PB |
615 | ) |
616 | ||
81632f11 RE |
617 | (define_insn_and_split "*negdf2_vfp" |
618 | [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r") | |
619 | (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))] | |
e0dc3601 | 620 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
81632f11 | 621 | "@ |
436c249d | 622 | vneg%?.f64\\t%P0, %P1 |
81632f11 RE |
623 | # |
624 | #" | |
e0dc3601 | 625 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed |
81632f11 RE |
626 | && arm_general_register_operand (operands[0], DFmode)" |
627 | [(set (match_dup 0) (match_dup 1))] | |
628 | " | |
629 | if (REGNO (operands[0]) == REGNO (operands[1])) | |
630 | { | |
631 | operands[0] = gen_highpart (SImode, operands[0]); | |
632 | operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000)); | |
633 | } | |
634 | else | |
635 | { | |
636 | rtx in_hi, in_lo, out_hi, out_lo; | |
637 | ||
638 | in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]), | |
639 | GEN_INT (0x80000000)); | |
640 | in_lo = gen_lowpart (SImode, operands[1]); | |
641 | out_hi = gen_highpart (SImode, operands[0]); | |
642 | out_lo = gen_lowpart (SImode, operands[0]); | |
643 | ||
644 | if (REGNO (in_lo) == REGNO (out_hi)) | |
645 | { | |
f7df4a84 | 646 | emit_insn (gen_rtx_SET (out_lo, in_lo)); |
81632f11 RE |
647 | operands[0] = out_hi; |
648 | operands[1] = in_hi; | |
649 | } | |
650 | else | |
651 | { | |
f7df4a84 | 652 | emit_insn (gen_rtx_SET (out_hi, in_hi)); |
81632f11 RE |
653 | operands[0] = out_lo; |
654 | operands[1] = in_lo; | |
655 | } | |
656 | } | |
657 | " | |
9b66ebb1 | 658 | [(set_attr "predicable" "yes") |
1572e697 | 659 | (set_attr "predicable_short_it" "no") |
81632f11 | 660 | (set_attr "length" "4,4,8") |
51c69ddb | 661 | (set_attr "type" "ffarithd")] |
9b66ebb1 PB |
662 | ) |
663 | ||
664 | ||
665 | ;; Arithmetic insns | |
666 | ||
667 | (define_insn "*addsf3_vfp" | |
f1adb0a9 JB |
668 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
669 | (plus:SF (match_operand:SF 1 "s_register_operand" "t") | |
670 | (match_operand:SF 2 "s_register_operand" "t")))] | |
5b3e6663 | 671 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
436c249d | 672 | "vadd%?.f32\\t%0, %1, %2" |
9b66ebb1 | 673 | [(set_attr "predicable" "yes") |
1572e697 | 674 | (set_attr "predicable_short_it" "no") |
51c69ddb | 675 | (set_attr "type" "fadds")] |
9b66ebb1 PB |
676 | ) |
677 | ||
678 | (define_insn "*adddf3_vfp" | |
679 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
680 | (plus:DF (match_operand:DF 1 "s_register_operand" "w") | |
681 | (match_operand:DF 2 "s_register_operand" "w")))] | |
e0dc3601 | 682 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
436c249d | 683 | "vadd%?.f64\\t%P0, %P1, %P2" |
9b66ebb1 | 684 | [(set_attr "predicable" "yes") |
1572e697 | 685 | (set_attr "predicable_short_it" "no") |
51c69ddb | 686 | (set_attr "type" "faddd")] |
9b66ebb1 PB |
687 | ) |
688 | ||
689 | ||
690 | (define_insn "*subsf3_vfp" | |
f1adb0a9 JB |
691 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
692 | (minus:SF (match_operand:SF 1 "s_register_operand" "t") | |
693 | (match_operand:SF 2 "s_register_operand" "t")))] | |
5b3e6663 | 694 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
436c249d | 695 | "vsub%?.f32\\t%0, %1, %2" |
9b66ebb1 | 696 | [(set_attr "predicable" "yes") |
1572e697 | 697 | (set_attr "predicable_short_it" "no") |
51c69ddb | 698 | (set_attr "type" "fadds")] |
9b66ebb1 PB |
699 | ) |
700 | ||
701 | (define_insn "*subdf3_vfp" | |
702 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
703 | (minus:DF (match_operand:DF 1 "s_register_operand" "w") | |
704 | (match_operand:DF 2 "s_register_operand" "w")))] | |
e0dc3601 | 705 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
436c249d | 706 | "vsub%?.f64\\t%P0, %P1, %P2" |
9b66ebb1 | 707 | [(set_attr "predicable" "yes") |
1572e697 | 708 | (set_attr "predicable_short_it" "no") |
51c69ddb | 709 | (set_attr "type" "faddd")] |
9b66ebb1 PB |
710 | ) |
711 | ||
712 | ||
713 | ;; Division insns | |
714 | ||
a89b02c0 RE |
715 | ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input |
716 | ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or | |
717 | ; earlier. | |
9b66ebb1 | 718 | (define_insn "*divsf3_vfp" |
a89b02c0 RE |
719 | [(set (match_operand:SF 0 "s_register_operand" "=&t,t") |
720 | (div:SF (match_operand:SF 1 "s_register_operand" "t,t") | |
721 | (match_operand:SF 2 "s_register_operand" "t,t")))] | |
5b3e6663 | 722 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
436c249d | 723 | "vdiv%?.f32\\t%0, %1, %2" |
9b66ebb1 | 724 | [(set_attr "predicable" "yes") |
1572e697 | 725 | (set_attr "predicable_short_it" "no") |
a89b02c0 | 726 | (set_attr "arch" "*,armv6_or_vfpv3") |
9b66ebb1 PB |
727 | (set_attr "type" "fdivs")] |
728 | ) | |
729 | ||
730 | (define_insn "*divdf3_vfp" | |
a89b02c0 RE |
731 | [(set (match_operand:DF 0 "s_register_operand" "=&w,w") |
732 | (div:DF (match_operand:DF 1 "s_register_operand" "w,w") | |
733 | (match_operand:DF 2 "s_register_operand" "w,w")))] | |
e0dc3601 | 734 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
436c249d | 735 | "vdiv%?.f64\\t%P0, %P1, %P2" |
9b66ebb1 | 736 | [(set_attr "predicable" "yes") |
1572e697 | 737 | (set_attr "predicable_short_it" "no") |
a89b02c0 | 738 | (set_attr "arch" "*,armv6_or_vfpv3") |
9b66ebb1 PB |
739 | (set_attr "type" "fdivd")] |
740 | ) | |
741 | ||
742 | ||
743 | ;; Multiplication insns | |
744 | ||
745 | (define_insn "*mulsf3_vfp" | |
0498a2be | 746 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
f1adb0a9 JB |
747 | (mult:SF (match_operand:SF 1 "s_register_operand" "t") |
748 | (match_operand:SF 2 "s_register_operand" "t")))] | |
5b3e6663 | 749 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14d9aa9f | 750 | "vmul%?.f32\\t%0, %1, %2" |
9b66ebb1 | 751 | [(set_attr "predicable" "yes") |
1572e697 | 752 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 753 | (set_attr "type" "fmuls")] |
9b66ebb1 PB |
754 | ) |
755 | ||
756 | (define_insn "*muldf3_vfp" | |
0498a2be | 757 | [(set (match_operand:DF 0 "s_register_operand" "=w") |
9b66ebb1 PB |
758 | (mult:DF (match_operand:DF 1 "s_register_operand" "w") |
759 | (match_operand:DF 2 "s_register_operand" "w")))] | |
e0dc3601 | 760 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14d9aa9f | 761 | "vmul%?.f64\\t%P0, %P1, %P2" |
9b66ebb1 | 762 | [(set_attr "predicable" "yes") |
1572e697 | 763 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 764 | (set_attr "type" "fmuld")] |
9b66ebb1 PB |
765 | ) |
766 | ||
9b66ebb1 | 767 | (define_insn "*mulsf3negsf_vfp" |
0498a2be | 768 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
f1adb0a9 JB |
769 | (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t")) |
770 | (match_operand:SF 2 "s_register_operand" "t")))] | |
1f71aee9 SN |
771 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && !flag_rounding_math" |
772 | "vnmul%?.f32\\t%0, %1, %2" | |
773 | [(set_attr "predicable" "yes") | |
774 | (set_attr "predicable_short_it" "no") | |
775 | (set_attr "type" "fmuls")] | |
776 | ) | |
777 | ||
778 | (define_insn "*negmulsf3_vfp" | |
779 | [(set (match_operand:SF 0 "s_register_operand" "=t") | |
780 | (neg:SF (mult:SF (match_operand:SF 1 "s_register_operand" "t") | |
781 | (match_operand:SF 2 "s_register_operand" "t"))))] | |
5b3e6663 | 782 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14d9aa9f | 783 | "vnmul%?.f32\\t%0, %1, %2" |
9b66ebb1 | 784 | [(set_attr "predicable" "yes") |
1572e697 | 785 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 786 | (set_attr "type" "fmuls")] |
9b66ebb1 PB |
787 | ) |
788 | ||
789 | (define_insn "*muldf3negdf_vfp" | |
0498a2be | 790 | [(set (match_operand:DF 0 "s_register_operand" "=w") |
9b66ebb1 PB |
791 | (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w")) |
792 | (match_operand:DF 2 "s_register_operand" "w")))] | |
1f71aee9 SN |
793 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE |
794 | && !flag_rounding_math" | |
795 | "vnmul%?.f64\\t%P0, %P1, %P2" | |
796 | [(set_attr "predicable" "yes") | |
797 | (set_attr "predicable_short_it" "no") | |
798 | (set_attr "type" "fmuld")] | |
799 | ) | |
800 | ||
801 | (define_insn "*negmuldf3_vfp" | |
802 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
803 | (neg:DF (mult:DF (match_operand:DF 1 "s_register_operand" "w") | |
804 | (match_operand:DF 2 "s_register_operand" "w"))))] | |
e0dc3601 | 805 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14d9aa9f | 806 | "vnmul%?.f64\\t%P0, %P1, %P2" |
9b66ebb1 | 807 | [(set_attr "predicable" "yes") |
1572e697 | 808 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 809 | (set_attr "type" "fmuld")] |
9b66ebb1 PB |
810 | ) |
811 | ||
812 | ||
813 | ;; Multiply-accumulate insns | |
814 | ||
815 | ;; 0 = 1 * 2 + 0 | |
816 | (define_insn "*mulsf3addsf_vfp" | |
f1adb0a9 JB |
817 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
818 | (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t") | |
819 | (match_operand:SF 3 "s_register_operand" "t")) | |
9b66ebb1 | 820 | (match_operand:SF 1 "s_register_operand" "0")))] |
5b3e6663 | 821 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14d9aa9f | 822 | "vmla%?.f32\\t%0, %2, %3" |
9b66ebb1 | 823 | [(set_attr "predicable" "yes") |
1572e697 | 824 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 825 | (set_attr "type" "fmacs")] |
9b66ebb1 PB |
826 | ) |
827 | ||
828 | (define_insn "*muldf3adddf_vfp" | |
829 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
830 | (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w") | |
831 | (match_operand:DF 3 "s_register_operand" "w")) | |
832 | (match_operand:DF 1 "s_register_operand" "0")))] | |
e0dc3601 | 833 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14d9aa9f | 834 | "vmla%?.f64\\t%P0, %P2, %P3" |
9b66ebb1 | 835 | [(set_attr "predicable" "yes") |
1572e697 | 836 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 837 | (set_attr "type" "fmacd")] |
9b66ebb1 PB |
838 | ) |
839 | ||
840 | ;; 0 = 1 * 2 - 0 | |
841 | (define_insn "*mulsf3subsf_vfp" | |
f1adb0a9 JB |
842 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
843 | (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t") | |
844 | (match_operand:SF 3 "s_register_operand" "t")) | |
9b66ebb1 | 845 | (match_operand:SF 1 "s_register_operand" "0")))] |
5b3e6663 | 846 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14d9aa9f | 847 | "vnmls%?.f32\\t%0, %2, %3" |
9b66ebb1 | 848 | [(set_attr "predicable" "yes") |
1572e697 | 849 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 850 | (set_attr "type" "fmacs")] |
9b66ebb1 PB |
851 | ) |
852 | ||
853 | (define_insn "*muldf3subdf_vfp" | |
854 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
855 | (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w") | |
856 | (match_operand:DF 3 "s_register_operand" "w")) | |
857 | (match_operand:DF 1 "s_register_operand" "0")))] | |
e0dc3601 | 858 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14d9aa9f | 859 | "vnmls%?.f64\\t%P0, %P2, %P3" |
9b66ebb1 | 860 | [(set_attr "predicable" "yes") |
1572e697 | 861 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 862 | (set_attr "type" "fmacd")] |
9b66ebb1 PB |
863 | ) |
864 | ||
865 | ;; 0 = -(1 * 2) + 0 | |
866 | (define_insn "*mulsf3negsfaddsf_vfp" | |
f1adb0a9 | 867 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
9b66ebb1 | 868 | (minus:SF (match_operand:SF 1 "s_register_operand" "0") |
f1adb0a9 JB |
869 | (mult:SF (match_operand:SF 2 "s_register_operand" "t") |
870 | (match_operand:SF 3 "s_register_operand" "t"))))] | |
5b3e6663 | 871 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14d9aa9f | 872 | "vmls%?.f32\\t%0, %2, %3" |
9b66ebb1 | 873 | [(set_attr "predicable" "yes") |
1572e697 | 874 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 875 | (set_attr "type" "fmacs")] |
9b66ebb1 PB |
876 | ) |
877 | ||
878 | (define_insn "*fmuldf3negdfadddf_vfp" | |
879 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
880 | (minus:DF (match_operand:DF 1 "s_register_operand" "0") | |
881 | (mult:DF (match_operand:DF 2 "s_register_operand" "w") | |
882 | (match_operand:DF 3 "s_register_operand" "w"))))] | |
e0dc3601 | 883 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14d9aa9f | 884 | "vmls%?.f64\\t%P0, %P2, %P3" |
9b66ebb1 | 885 | [(set_attr "predicable" "yes") |
1572e697 | 886 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 887 | (set_attr "type" "fmacd")] |
9b66ebb1 PB |
888 | ) |
889 | ||
890 | ||
891 | ;; 0 = -(1 * 2) - 0 | |
892 | (define_insn "*mulsf3negsfsubsf_vfp" | |
f1adb0a9 | 893 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
9b66ebb1 | 894 | (minus:SF (mult:SF |
f1adb0a9 JB |
895 | (neg:SF (match_operand:SF 2 "s_register_operand" "t")) |
896 | (match_operand:SF 3 "s_register_operand" "t")) | |
9b66ebb1 | 897 | (match_operand:SF 1 "s_register_operand" "0")))] |
5b3e6663 | 898 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14d9aa9f | 899 | "vnmla%?.f32\\t%0, %2, %3" |
9b66ebb1 | 900 | [(set_attr "predicable" "yes") |
1572e697 | 901 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 902 | (set_attr "type" "fmacs")] |
9b66ebb1 PB |
903 | ) |
904 | ||
905 | (define_insn "*muldf3negdfsubdf_vfp" | |
906 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
907 | (minus:DF (mult:DF | |
908 | (neg:DF (match_operand:DF 2 "s_register_operand" "w")) | |
909 | (match_operand:DF 3 "s_register_operand" "w")) | |
910 | (match_operand:DF 1 "s_register_operand" "0")))] | |
e0dc3601 | 911 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14d9aa9f | 912 | "vnmla%?.f64\\t%P0, %P2, %P3" |
9b66ebb1 | 913 | [(set_attr "predicable" "yes") |
1572e697 | 914 | (set_attr "predicable_short_it" "no") |
a8e17e9e | 915 | (set_attr "type" "fmacd")] |
9b66ebb1 PB |
916 | ) |
917 | ||
76f722f4 MGD |
918 | ;; Fused-multiply-accumulate |
919 | ||
920 | (define_insn "fma<SDF:mode>4" | |
921 | [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") | |
922 | (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") | |
923 | (match_operand:SDF 2 "register_operand" "<F_constraint>") | |
924 | (match_operand:SDF 3 "register_operand" "0")))] | |
925 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA" | |
926 | "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
927 | [(set_attr "predicable" "yes") | |
1572e697 | 928 | (set_attr "predicable_short_it" "no") |
29637783 | 929 | (set_attr "type" "ffma<vfp_type>")] |
76f722f4 MGD |
930 | ) |
931 | ||
932 | (define_insn "*fmsub<SDF:mode>4" | |
933 | [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") | |
934 | (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand" | |
935 | "<F_constraint>")) | |
936 | (match_operand:SDF 2 "register_operand" "<F_constraint>") | |
937 | (match_operand:SDF 3 "register_operand" "0")))] | |
938 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA" | |
939 | "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
940 | [(set_attr "predicable" "yes") | |
1572e697 | 941 | (set_attr "predicable_short_it" "no") |
29637783 | 942 | (set_attr "type" "ffma<vfp_type>")] |
76f722f4 MGD |
943 | ) |
944 | ||
945 | (define_insn "*fnmsub<SDF:mode>4" | |
946 | [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") | |
947 | (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") | |
948 | (match_operand:SDF 2 "register_operand" "<F_constraint>") | |
949 | (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))] | |
950 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA" | |
951 | "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
952 | [(set_attr "predicable" "yes") | |
1572e697 | 953 | (set_attr "predicable_short_it" "no") |
29637783 | 954 | (set_attr "type" "ffma<vfp_type>")] |
76f722f4 MGD |
955 | ) |
956 | ||
957 | (define_insn "*fnmadd<SDF:mode>4" | |
958 | [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") | |
959 | (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand" | |
960 | "<F_constraint>")) | |
961 | (match_operand:SDF 2 "register_operand" "<F_constraint>") | |
962 | (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))] | |
963 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA" | |
964 | "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" | |
965 | [(set_attr "predicable" "yes") | |
1572e697 | 966 | (set_attr "predicable_short_it" "no") |
29637783 | 967 | (set_attr "type" "ffma<vfp_type>")] |
76f722f4 MGD |
968 | ) |
969 | ||
9b66ebb1 PB |
970 | |
971 | ;; Conversion routines | |
972 | ||
973 | (define_insn "*extendsfdf2_vfp" | |
974 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
f1adb0a9 | 975 | (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))] |
e0dc3601 | 976 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14a082a3 | 977 | "vcvt%?.f64.f32\\t%P0, %1" |
9b66ebb1 | 978 | [(set_attr "predicable" "yes") |
1572e697 | 979 | (set_attr "predicable_short_it" "no") |
75fe7b2f | 980 | (set_attr "type" "f_cvt")] |
9b66ebb1 PB |
981 | ) |
982 | ||
983 | (define_insn "*truncdfsf2_vfp" | |
f1adb0a9 | 984 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
9b66ebb1 | 985 | (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))] |
e0dc3601 | 986 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14a082a3 | 987 | "vcvt%?.f32.f64\\t%0, %P1" |
9b66ebb1 | 988 | [(set_attr "predicable" "yes") |
1572e697 | 989 | (set_attr "predicable_short_it" "no") |
75fe7b2f | 990 | (set_attr "type" "f_cvt")] |
9b66ebb1 PB |
991 | ) |
992 | ||
0fd8c3ad SL |
993 | (define_insn "extendhfsf2" |
994 | [(set (match_operand:SF 0 "s_register_operand" "=t") | |
995 | (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))] | |
e0dc3601 | 996 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16" |
0fd8c3ad SL |
997 | "vcvtb%?.f32.f16\\t%0, %1" |
998 | [(set_attr "predicable" "yes") | |
1572e697 | 999 | (set_attr "predicable_short_it" "no") |
0fd8c3ad SL |
1000 | (set_attr "type" "f_cvt")] |
1001 | ) | |
1002 | ||
1003 | (define_insn "truncsfhf2" | |
1004 | [(set (match_operand:HF 0 "s_register_operand" "=t") | |
1005 | (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))] | |
e0dc3601 | 1006 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16" |
0fd8c3ad SL |
1007 | "vcvtb%?.f16.f32\\t%0, %1" |
1008 | [(set_attr "predicable" "yes") | |
1572e697 | 1009 | (set_attr "predicable_short_it" "no") |
0fd8c3ad SL |
1010 | (set_attr "type" "f_cvt")] |
1011 | ) | |
1012 | ||
9b66ebb1 | 1013 | (define_insn "*truncsisf2_vfp" |
f1adb0a9 JB |
1014 | [(set (match_operand:SI 0 "s_register_operand" "=t") |
1015 | (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))] | |
5b3e6663 | 1016 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14a082a3 | 1017 | "vcvt%?.s32.f32\\t%0, %1" |
9b66ebb1 | 1018 | [(set_attr "predicable" "yes") |
1572e697 | 1019 | (set_attr "predicable_short_it" "no") |
7b49c9e1 | 1020 | (set_attr "type" "f_cvtf2i")] |
9b66ebb1 PB |
1021 | ) |
1022 | ||
1023 | (define_insn "*truncsidf2_vfp" | |
f1adb0a9 | 1024 | [(set (match_operand:SI 0 "s_register_operand" "=t") |
9b66ebb1 | 1025 | (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))] |
e0dc3601 | 1026 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14a082a3 | 1027 | "vcvt%?.s32.f64\\t%0, %P1" |
9b66ebb1 | 1028 | [(set_attr "predicable" "yes") |
1572e697 | 1029 | (set_attr "predicable_short_it" "no") |
7b49c9e1 | 1030 | (set_attr "type" "f_cvtf2i")] |
9b66ebb1 PB |
1031 | ) |
1032 | ||
6f6c1f6d PB |
1033 | |
1034 | (define_insn "fixuns_truncsfsi2" | |
f1adb0a9 JB |
1035 | [(set (match_operand:SI 0 "s_register_operand" "=t") |
1036 | (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))] | |
5b3e6663 | 1037 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14a082a3 | 1038 | "vcvt%?.u32.f32\\t%0, %1" |
6f6c1f6d | 1039 | [(set_attr "predicable" "yes") |
1572e697 | 1040 | (set_attr "predicable_short_it" "no") |
7b49c9e1 | 1041 | (set_attr "type" "f_cvtf2i")] |
6f6c1f6d PB |
1042 | ) |
1043 | ||
1044 | (define_insn "fixuns_truncdfsi2" | |
f1adb0a9 JB |
1045 | [(set (match_operand:SI 0 "s_register_operand" "=t") |
1046 | (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))] | |
e0dc3601 | 1047 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14a082a3 | 1048 | "vcvt%?.u32.f64\\t%0, %P1" |
6f6c1f6d | 1049 | [(set_attr "predicable" "yes") |
1572e697 | 1050 | (set_attr "predicable_short_it" "no") |
7b49c9e1 | 1051 | (set_attr "type" "f_cvtf2i")] |
6f6c1f6d PB |
1052 | ) |
1053 | ||
1054 | ||
9b66ebb1 | 1055 | (define_insn "*floatsisf2_vfp" |
f1adb0a9 JB |
1056 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
1057 | (float:SF (match_operand:SI 1 "s_register_operand" "t")))] | |
5b3e6663 | 1058 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14a082a3 | 1059 | "vcvt%?.f32.s32\\t%0, %1" |
9b66ebb1 | 1060 | [(set_attr "predicable" "yes") |
1572e697 | 1061 | (set_attr "predicable_short_it" "no") |
7b49c9e1 | 1062 | (set_attr "type" "f_cvti2f")] |
9b66ebb1 PB |
1063 | ) |
1064 | ||
1065 | (define_insn "*floatsidf2_vfp" | |
1066 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
f1adb0a9 | 1067 | (float:DF (match_operand:SI 1 "s_register_operand" "t")))] |
e0dc3601 | 1068 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14a082a3 | 1069 | "vcvt%?.f64.s32\\t%P0, %1" |
9b66ebb1 | 1070 | [(set_attr "predicable" "yes") |
1572e697 | 1071 | (set_attr "predicable_short_it" "no") |
7b49c9e1 | 1072 | (set_attr "type" "f_cvti2f")] |
9b66ebb1 PB |
1073 | ) |
1074 | ||
1075 | ||
6f6c1f6d | 1076 | (define_insn "floatunssisf2" |
f1adb0a9 JB |
1077 | [(set (match_operand:SF 0 "s_register_operand" "=t") |
1078 | (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))] | |
5b3e6663 | 1079 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
14a082a3 | 1080 | "vcvt%?.f32.u32\\t%0, %1" |
6f6c1f6d | 1081 | [(set_attr "predicable" "yes") |
1572e697 | 1082 | (set_attr "predicable_short_it" "no") |
7b49c9e1 | 1083 | (set_attr "type" "f_cvti2f")] |
6f6c1f6d PB |
1084 | ) |
1085 | ||
1086 | (define_insn "floatunssidf2" | |
1087 | [(set (match_operand:DF 0 "s_register_operand" "=w") | |
f1adb0a9 | 1088 | (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))] |
e0dc3601 | 1089 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
14a082a3 | 1090 | "vcvt%?.f64.u32\\t%P0, %1" |
6f6c1f6d | 1091 | [(set_attr "predicable" "yes") |
1572e697 | 1092 | (set_attr "predicable_short_it" "no") |
7b49c9e1 | 1093 | (set_attr "type" "f_cvti2f")] |
6f6c1f6d PB |
1094 | ) |
1095 | ||
1096 | ||
9b66ebb1 PB |
1097 | ;; Sqrt insns. |
1098 | ||
a89b02c0 RE |
1099 | ; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input |
1100 | ; operands, so mark the output as early clobber for VFPv2 on ARMv5 or | |
1101 | ; earlier. | |
9b66ebb1 | 1102 | (define_insn "*sqrtsf2_vfp" |
a89b02c0 RE |
1103 | [(set (match_operand:SF 0 "s_register_operand" "=&t,t") |
1104 | (sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))] | |
5b3e6663 | 1105 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
c2786584 | 1106 | "vsqrt%?.f32\\t%0, %1" |
9b66ebb1 | 1107 | [(set_attr "predicable" "yes") |
1572e697 | 1108 | (set_attr "predicable_short_it" "no") |
a89b02c0 | 1109 | (set_attr "arch" "*,armv6_or_vfpv3") |
b86923f0 | 1110 | (set_attr "type" "fsqrts")] |
9b66ebb1 PB |
1111 | ) |
1112 | ||
1113 | (define_insn "*sqrtdf2_vfp" | |
a89b02c0 RE |
1114 | [(set (match_operand:DF 0 "s_register_operand" "=&w,w") |
1115 | (sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))] | |
e0dc3601 | 1116 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
c2786584 | 1117 | "vsqrt%?.f64\\t%P0, %P1" |
9b66ebb1 | 1118 | [(set_attr "predicable" "yes") |
1572e697 | 1119 | (set_attr "predicable_short_it" "no") |
a89b02c0 | 1120 | (set_attr "arch" "*,armv6_or_vfpv3") |
b86923f0 | 1121 | (set_attr "type" "fsqrtd")] |
9b66ebb1 PB |
1122 | ) |
1123 | ||
1124 | ||
1125 | ;; Patterns to split/copy vfp condition flags. | |
1126 | ||
1127 | (define_insn "*movcc_vfp" | |
1128 | [(set (reg CC_REGNUM) | |
1129 | (reg VFPCC_REGNUM))] | |
5b3e6663 | 1130 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
5a150108 | 1131 | "vmrs%?\\tAPSR_nzcv, FPSCR" |
9b66ebb1 | 1132 | [(set_attr "conds" "set") |
75fe7b2f | 1133 | (set_attr "type" "f_flag")] |
9b66ebb1 PB |
1134 | ) |
1135 | ||
1136 | (define_insn_and_split "*cmpsf_split_vfp" | |
1137 | [(set (reg:CCFP CC_REGNUM) | |
f1adb0a9 JB |
1138 | (compare:CCFP (match_operand:SF 0 "s_register_operand" "t") |
1139 | (match_operand:SF 1 "vfp_compare_operand" "tG")))] | |
5b3e6663 | 1140 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
9b66ebb1 | 1141 | "#" |
5b3e6663 | 1142 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
9b66ebb1 PB |
1143 | [(set (reg:CCFP VFPCC_REGNUM) |
1144 | (compare:CCFP (match_dup 0) | |
1145 | (match_dup 1))) | |
1146 | (set (reg:CCFP CC_REGNUM) | |
1147 | (reg:CCFP VFPCC_REGNUM))] | |
1148 | "" | |
1149 | ) | |
1150 | ||
1151 | (define_insn_and_split "*cmpsf_trap_split_vfp" | |
1152 | [(set (reg:CCFPE CC_REGNUM) | |
f1adb0a9 JB |
1153 | (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t") |
1154 | (match_operand:SF 1 "vfp_compare_operand" "tG")))] | |
5b3e6663 | 1155 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
9b66ebb1 | 1156 | "#" |
5b3e6663 | 1157 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
9b66ebb1 PB |
1158 | [(set (reg:CCFPE VFPCC_REGNUM) |
1159 | (compare:CCFPE (match_dup 0) | |
1160 | (match_dup 1))) | |
1161 | (set (reg:CCFPE CC_REGNUM) | |
1162 | (reg:CCFPE VFPCC_REGNUM))] | |
1163 | "" | |
1164 | ) | |
1165 | ||
1166 | (define_insn_and_split "*cmpdf_split_vfp" | |
1167 | [(set (reg:CCFP CC_REGNUM) | |
1168 | (compare:CCFP (match_operand:DF 0 "s_register_operand" "w") | |
1169 | (match_operand:DF 1 "vfp_compare_operand" "wG")))] | |
e0dc3601 | 1170 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
9b66ebb1 | 1171 | "#" |
e0dc3601 | 1172 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
9b66ebb1 PB |
1173 | [(set (reg:CCFP VFPCC_REGNUM) |
1174 | (compare:CCFP (match_dup 0) | |
1175 | (match_dup 1))) | |
1176 | (set (reg:CCFP CC_REGNUM) | |
510bc854 | 1177 | (reg:CCFP VFPCC_REGNUM))] |
9b66ebb1 PB |
1178 | "" |
1179 | ) | |
1180 | ||
1181 | (define_insn_and_split "*cmpdf_trap_split_vfp" | |
1182 | [(set (reg:CCFPE CC_REGNUM) | |
1183 | (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w") | |
1184 | (match_operand:DF 1 "vfp_compare_operand" "wG")))] | |
e0dc3601 | 1185 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
9b66ebb1 | 1186 | "#" |
e0dc3601 | 1187 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
9b66ebb1 PB |
1188 | [(set (reg:CCFPE VFPCC_REGNUM) |
1189 | (compare:CCFPE (match_dup 0) | |
1190 | (match_dup 1))) | |
1191 | (set (reg:CCFPE CC_REGNUM) | |
1192 | (reg:CCFPE VFPCC_REGNUM))] | |
1193 | "" | |
1194 | ) | |
1195 | ||
1196 | ||
1197 | ;; Comparison patterns | |
1198 | ||
c2786584 KT |
1199 | ;; In the compare with FP zero case the ARM Architecture Reference Manual |
1200 | ;; specifies the immediate to be #0.0. However, some buggy assemblers only | |
1201 | ;; accept #0. We don't want to autodetect broken assemblers, so output #0. | |
9b66ebb1 PB |
1202 | (define_insn "*cmpsf_vfp" |
1203 | [(set (reg:CCFP VFPCC_REGNUM) | |
f1adb0a9 JB |
1204 | (compare:CCFP (match_operand:SF 0 "s_register_operand" "t,t") |
1205 | (match_operand:SF 1 "vfp_compare_operand" "t,G")))] | |
5b3e6663 | 1206 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
9b66ebb1 | 1207 | "@ |
c2786584 KT |
1208 | vcmp%?.f32\\t%0, %1 |
1209 | vcmp%?.f32\\t%0, #0" | |
9b66ebb1 | 1210 | [(set_attr "predicable" "yes") |
1572e697 | 1211 | (set_attr "predicable_short_it" "no") |
51c69ddb | 1212 | (set_attr "type" "fcmps")] |
9b66ebb1 PB |
1213 | ) |
1214 | ||
1215 | (define_insn "*cmpsf_trap_vfp" | |
1216 | [(set (reg:CCFPE VFPCC_REGNUM) | |
f1adb0a9 JB |
1217 | (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t,t") |
1218 | (match_operand:SF 1 "vfp_compare_operand" "t,G")))] | |
5b3e6663 | 1219 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
9b66ebb1 | 1220 | "@ |
c2786584 KT |
1221 | vcmpe%?.f32\\t%0, %1 |
1222 | vcmpe%?.f32\\t%0, #0" | |
9b66ebb1 | 1223 | [(set_attr "predicable" "yes") |
1572e697 | 1224 | (set_attr "predicable_short_it" "no") |
7dd8ecf0 | 1225 | (set_attr "type" "fcmps")] |
9b66ebb1 PB |
1226 | ) |
1227 | ||
1228 | (define_insn "*cmpdf_vfp" | |
1229 | [(set (reg:CCFP VFPCC_REGNUM) | |
1230 | (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w") | |
1231 | (match_operand:DF 1 "vfp_compare_operand" "w,G")))] | |
e0dc3601 | 1232 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
9b66ebb1 | 1233 | "@ |
c2786584 KT |
1234 | vcmp%?.f64\\t%P0, %P1 |
1235 | vcmp%?.f64\\t%P0, #0" | |
9b66ebb1 | 1236 | [(set_attr "predicable" "yes") |
1572e697 | 1237 | (set_attr "predicable_short_it" "no") |
51c69ddb | 1238 | (set_attr "type" "fcmpd")] |
9b66ebb1 PB |
1239 | ) |
1240 | ||
1241 | (define_insn "*cmpdf_trap_vfp" | |
1242 | [(set (reg:CCFPE VFPCC_REGNUM) | |
1243 | (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w") | |
1244 | (match_operand:DF 1 "vfp_compare_operand" "w,G")))] | |
e0dc3601 | 1245 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" |
9b66ebb1 | 1246 | "@ |
c2786584 KT |
1247 | vcmpe%?.f64\\t%P0, %P1 |
1248 | vcmpe%?.f64\\t%P0, #0" | |
9b66ebb1 | 1249 | [(set_attr "predicable" "yes") |
1572e697 | 1250 | (set_attr "predicable_short_it" "no") |
51c69ddb | 1251 | (set_attr "type" "fcmpd")] |
9b66ebb1 PB |
1252 | ) |
1253 | ||
d742ff4b | 1254 | ;; Fixed point to floating point conversions. |
7f3d8f56 RR |
1255 | (define_code_iterator FCVT [unsigned_float float]) |
1256 | (define_code_attr FCVTI32typename [(unsigned_float "u32") (float "s32")]) | |
1257 | ||
1258 | (define_insn "*combine_vcvt_f32_<FCVTI32typename>" | |
1259 | [(set (match_operand:SF 0 "s_register_operand" "=t") | |
1260 | (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0")) | |
d742ff4b | 1261 | (match_operand 2 |
7f3d8f56 RR |
1262 | "const_double_vcvt_power_of_two_reciprocal" "Dt")))] |
1263 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math" | |
d742ff4b RE |
1264 | "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2" |
1265 | [(set_attr "predicable" "yes") | |
1266 | (set_attr "predicable_short_it" "no") | |
1267 | (set_attr "type" "f_cvti2f")] | |
7f3d8f56 | 1268 | ) |
9b66ebb1 | 1269 | |
7f3d8f56 RR |
1270 | ;; Not the ideal way of implementing this. Ideally we would be able to split |
1271 | ;; this into a move to a DP register and then a vcvt.f64.i32 | |
1272 | (define_insn "*combine_vcvt_f64_<FCVTI32typename>" | |
1273 | [(set (match_operand:DF 0 "s_register_operand" "=x,x,w") | |
1274 | (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r")) | |
d742ff4b | 1275 | (match_operand 2 |
7f3d8f56 | 1276 | "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))] |
d742ff4b | 1277 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math |
7f3d8f56 RR |
1278 | && !TARGET_VFP_SINGLE" |
1279 | "@ | |
d742ff4b RE |
1280 | vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2 |
1281 | vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2 | |
1282 | vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2" | |
1283 | [(set_attr "predicable" "yes") | |
1284 | (set_attr "ce_count" "2") | |
1285 | (set_attr "predicable_short_it" "no") | |
1286 | (set_attr "type" "f_cvti2f") | |
1287 | (set_attr "length" "8")] | |
7f3d8f56 | 1288 | ) |
9b66ebb1 | 1289 | |
c75d51aa | 1290 | (define_insn "*combine_vcvtf2i" |
d31e00d4 RR |
1291 | [(set (match_operand:SI 0 "s_register_operand" "=t") |
1292 | (fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0") | |
c75d51aa RL |
1293 | (match_operand 2 |
1294 | "const_double_vcvt_power_of_two" "Dp")))))] | |
1295 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math" | |
d31e00d4 | 1296 | "vcvt%?.s32.f32\\t%0, %1, %v2" |
c75d51aa RL |
1297 | [(set_attr "predicable" "yes") |
1298 | (set_attr "predicable_short_it" "no") | |
d31e00d4 | 1299 | (set_attr "type" "f_cvtf2i")] |
c75d51aa RL |
1300 | ) |
1301 | ||
7f3d8f56 | 1302 | ;; Store multiple insn used in function prologue. |
9b66ebb1 PB |
1303 | (define_insn "*push_multi_vfp" |
1304 | [(match_parallel 2 "multi_register_push" | |
1305 | [(set (match_operand:BLK 0 "memory_operand" "=m") | |
4e6f5666 | 1306 | (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")] |
9b66ebb1 | 1307 | UNSPEC_PUSH_MULT))])] |
5b3e6663 | 1308 | "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" |
b27832ed | 1309 | "* return vfp_output_vstmd (operands);" |
75fe7b2f | 1310 | [(set_attr "type" "f_stored")] |
9b66ebb1 PB |
1311 | ) |
1312 | ||
1dd4fe1f KT |
1313 | ;; VRINT round to integral instructions. |
1314 | ;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2, | |
1315 | ;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2, | |
1316 | ;; rintsf2, rintdf2. | |
1317 | (define_insn "<vrint_pattern><SDF:mode>2" | |
1318 | [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") | |
1319 | (unspec:SDF [(match_operand:SDF 1 | |
1320 | "register_operand" "<F_constraint>")] | |
1321 | VRINT))] | |
2f6403f1 | 1322 | "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>" |
1dd4fe1f KT |
1323 | "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1" |
1324 | [(set_attr "predicable" "<vrint_predicable>") | |
1572e697 | 1325 | (set_attr "predicable_short_it" "no") |
fca0efeb KT |
1326 | (set_attr "type" "f_rint<vfp_type>") |
1327 | (set_attr "conds" "<vrint_conds>")] | |
1dd4fe1f | 1328 | ) |
9b66ebb1 | 1329 | |
ababd936 KT |
1330 | ;; Implements the lround, lfloor and lceil optabs. |
1331 | (define_insn "l<vrint_pattern><su_optab><mode>si2" | |
1332 | [(set (match_operand:SI 0 "register_operand" "=t") | |
1333 | (FIXUORS:SI (unspec:SDF | |
1334 | [(match_operand:SDF 1 | |
1335 | "register_operand" "<F_constraint>")] VCVT)))] | |
1336 | "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>" | |
1337 | "vcvt<vrint_variant>%?.<su>32.<V_if_elem>\\t%0, %<V_reg>1" | |
1338 | [(set_attr "predicable" "no") | |
1339 | (set_attr "type" "f_cvtf2i")] | |
1340 | ) | |
1341 | ||
37202071 KT |
1342 | ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL. |
1343 | ;; The 'smax' and 'smin' RTL standard pattern names do not specify which | |
1344 | ;; operand will be returned when both operands are zero (i.e. they may not | |
1345 | ;; honour signed zeroes), or when either operand is NaN. Therefore GCC | |
1346 | ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring | |
1347 | ;; NaNs. | |
1348 | ||
1349 | (define_insn "smax<mode>3" | |
1350 | [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") | |
1351 | (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") | |
1352 | (match_operand:SDF 2 "register_operand" "<F_constraint>")))] | |
2f6403f1 | 1353 | "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>" |
37202071 | 1354 | "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" |
fca0efeb KT |
1355 | [(set_attr "type" "f_minmax<vfp_type>") |
1356 | (set_attr "conds" "unconditional")] | |
37202071 KT |
1357 | ) |
1358 | ||
1359 | (define_insn "smin<mode>3" | |
1360 | [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") | |
1361 | (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") | |
1362 | (match_operand:SDF 2 "register_operand" "<F_constraint>")))] | |
2f6403f1 | 1363 | "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>" |
37202071 | 1364 | "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" |
fca0efeb KT |
1365 | [(set_attr "type" "f_minmax<vfp_type>") |
1366 | (set_attr "conds" "unconditional")] | |
37202071 KT |
1367 | ) |
1368 | ||
f10743d3 KV |
1369 | ;; Write Floating-point Status and Control Register. |
1370 | (define_insn "set_fpscr" | |
1371 | [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)] | |
5db37871 | 1372 | "TARGET_VFP && TARGET_HARD_FLOAT" |
f10743d3 KV |
1373 | "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR" |
1374 | [(set_attr "type" "mrs")]) | |
1375 | ||
1376 | ;; Read Floating-point Status and Control Register. | |
1377 | (define_insn "get_fpscr" | |
1378 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1379 | (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))] | |
5db37871 | 1380 | "TARGET_VFP && TARGET_HARD_FLOAT" |
f10743d3 KV |
1381 | "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR" |
1382 | [(set_attr "type" "mrs")]) | |
1383 | ||
1384 | ||
9b66ebb1 PB |
1385 | ;; Unimplemented insns: |
1386 | ;; fldm* | |
1387 | ;; fstm* | |
1388 | ;; fmdhr et al (VFPv1) | |
59b9a953 | 1389 | ;; Support for xD (single precision only) variants. |
9b66ebb1 | 1390 | ;; fmrrs, fmsrr |