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