1;; ARM VFP instruction patterns 2;; Copyright (C) 2003-2020 Free Software Foundation, Inc. 3;; Written by CodeSourcery. 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 9;; the Free Software Foundation; either version 3, or (at your option) 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 18;; along with GCC; see the file COPYING3. If not see 19;; <http://www.gnu.org/licenses/>. */ 20 21;; Patterns for HI moves which provide more data transfer instructions when VFP 22;; support is enabled. 23(define_insn "*arm_movhi_vfp" 24 [(set 25 (match_operand:HI 0 "nonimmediate_operand" 26 "=rk, r, r, m, r, *t, r, *t") 27 (match_operand:HI 1 "general_operand" 28 "rIk, K, n, r, mi, r, *t, *t"))] 29 "TARGET_ARM && TARGET_HARD_FLOAT 30 && !TARGET_VFP_FP16INST 31 && (register_operand (operands[0], HImode) 32 || register_operand (operands[1], HImode))" 33{ 34 switch (which_alternative) 35 { 36 case 0: 37 return "mov%?\t%0, %1\t%@ movhi"; 38 case 1: 39 return "mvn%?\t%0, #%B1\t%@ movhi"; 40 case 2: 41 return "movw%?\t%0, %L1\t%@ movhi"; 42 case 3: 43 return "strh%?\t%1, %0\t%@ movhi"; 44 case 4: 45 return "ldrh%?\t%0, %1\t%@ movhi"; 46 case 5: 47 case 6: 48 return "vmov%?\t%0, %1\t%@ int"; 49 case 7: 50 return "vmov%?.f32\t%0, %1\t%@ int"; 51 default: 52 gcc_unreachable (); 53 } 54} 55 [(set_attr "predicable" "yes") 56 (set_attr_alternative "type" 57 [(if_then_else 58 (match_operand 1 "const_int_operand" "") 59 (const_string "mov_imm") 60 (const_string "mov_reg")) 61 (const_string "mvn_imm") 62 (const_string "mov_imm") 63 (const_string "store_4") 64 (const_string "load_4") 65 (const_string "f_mcr") 66 (const_string "f_mrc") 67 (const_string "fmov")]) 68 (set_attr "arch" "*, *, v6t2, *, *, *, *, *") 69 (set_attr "pool_range" "*, *, *, *, 256, *, *, *") 70 (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *") 71 (set_attr "length" "4")] 72) 73 74(define_insn "*thumb2_movhi_vfp" 75 [(set 76 (match_operand:HI 0 "nonimmediate_operand" 77 "=rk, r, l, r, m, r, *t, r, *t, Up, r") 78 (match_operand:HI 1 "general_operand" 79 "rk, I, Py, n, r, m, r, *t, *t, r, Up"))] 80 "TARGET_THUMB2 && TARGET_VFP_BASE 81 && !TARGET_VFP_FP16INST 82 && (register_operand (operands[0], HImode) 83 || register_operand (operands[1], HImode))" 84{ 85 switch (which_alternative) 86 { 87 case 0: 88 case 1: 89 case 2: 90 return "mov%?\t%0, %1\t%@ movhi"; 91 case 3: 92 return "movw%?\t%0, %L1\t%@ movhi"; 93 case 4: 94 return "strh%?\t%1, %0\t%@ movhi"; 95 case 5: 96 return "ldrh%?\t%0, %1\t%@ movhi"; 97 case 6: 98 case 7: 99 return "vmov%?\t%0, %1\t%@ int"; 100 case 8: 101 return "vmov%?.f32\t%0, %1\t%@ int"; 102 case 9: 103 return "vmsr%?\t P0, %1\t@ movhi"; 104 case 10: 105 return "vmrs%?\t %0, P0\t@ movhi"; 106 default: 107 gcc_unreachable (); 108 } 109} 110 [(set_attr "predicable" "yes") 111 (set_attr "predicable_short_it" 112 "yes, no, yes, no, no, no, no, no, no, no, no") 113 (set_attr "type" 114 "mov_reg, mov_imm, mov_imm, mov_imm, store_4, load_4,\ 115 f_mcr, f_mrc, fmov, mve_move, mve_move") 116 (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *, mve, mve") 117 (set_attr "pool_range" "*, *, *, *, *, 4094, *, *, *, *, *") 118 (set_attr "neg_pool_range" "*, *, *, *, *, 250, *, *, *, *, *") 119 (set_attr "length" "2, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4")] 120) 121 122;; Patterns for HI moves which provide more data transfer instructions when FP16 123;; instructions are available. 124(define_insn "*arm_movhi_fp16" 125 [(set 126 (match_operand:HI 0 "nonimmediate_operand" 127 "=r, r, r, m, r, *t, r, *t") 128 (match_operand:HI 1 "general_operand" 129 "rIk, K, n, r, mi, r, *t, *t"))] 130 "TARGET_ARM && TARGET_VFP_FP16INST 131 && (register_operand (operands[0], HImode) 132 || register_operand (operands[1], HImode))" 133{ 134 switch (which_alternative) 135 { 136 case 0: 137 return "mov%?\t%0, %1\t%@ movhi"; 138 case 1: 139 return "mvn%?\t%0, #%B1\t%@ movhi"; 140 case 2: 141 return "movw%?\t%0, %L1\t%@ movhi"; 142 case 3: 143 return "strh%?\t%1, %0\t%@ movhi"; 144 case 4: 145 return "ldrh%?\t%0, %1\t%@ movhi"; 146 case 5: 147 case 6: 148 return "vmov.f16\t%0, %1\t%@ int"; 149 case 7: 150 return "vmov%?.f32\t%0, %1\t%@ int"; 151 default: 152 gcc_unreachable (); 153 } 154} 155 [(set_attr "predicable" "yes, yes, yes, yes, yes, no, no, yes") 156 (set_attr_alternative "type" 157 [(if_then_else 158 (match_operand 1 "const_int_operand" "") 159 (const_string "mov_imm") 160 (const_string "mov_reg")) 161 (const_string "mvn_imm") 162 (const_string "mov_imm") 163 (const_string "store_4") 164 (const_string "load_4") 165 (const_string "f_mcr") 166 (const_string "f_mrc") 167 (const_string "fmov")]) 168 (set_attr "arch" "*, *, v6t2, *, *, *, *, *") 169 (set_attr "pool_range" "*, *, *, *, 256, *, *, *") 170 (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *") 171 (set_attr "length" "4")] 172) 173 174(define_insn "*thumb2_movhi_fp16" 175 [(set 176 (match_operand:HI 0 "nonimmediate_operand" 177 "=rk, r, l, r, m, r, *t, r, *t, Up, r") 178 (match_operand:HI 1 "general_operand" 179 "rk, I, Py, n, r, m, r, *t, *t, r, Up"))] 180 "TARGET_THUMB2 && (TARGET_VFP_FP16INST || TARGET_HAVE_MVE) 181 && (register_operand (operands[0], HImode) 182 || register_operand (operands[1], HImode))" 183{ 184 switch (which_alternative) 185 { 186 case 0: 187 case 1: 188 case 2: 189 return "mov%?\t%0, %1\t%@ movhi"; 190 case 3: 191 return "movw%?\t%0, %L1\t%@ movhi"; 192 case 4: 193 return "strh%?\t%1, %0\t%@ movhi"; 194 case 5: 195 return "ldrh%?\t%0, %1\t%@ movhi"; 196 case 6: 197 case 7: 198 return "vmov.f16\t%0, %1\t%@ int"; 199 case 8: 200 return "vmov%?.f32\t%0, %1\t%@ int"; 201 case 9: 202 return "vmsr%?\t P0, %1\t%@ movhi"; 203 case 10: 204 return "vmrs%?\t%0, P0\t%@ movhi"; 205 default: 206 gcc_unreachable (); 207 } 208} 209 [(set_attr "predicable" 210 "yes, yes, yes, yes, yes, yes, no, no, yes, yes, yes") 211 (set_attr "predicable_short_it" 212 "yes, no, yes, no, no, no, no, no, no, no, no") 213 (set_attr "type" 214 "mov_reg, mov_imm, mov_imm, mov_imm, store_4, load_4,\ 215 f_mcr, f_mrc, fmov, mve_move, mve_move") 216 (set_attr "arch" "*, *, *, v6t2, *, *, *, *, *, mve, mve") 217 (set_attr "pool_range" "*, *, *, *, *, 4094, *, *, *, *, *") 218 (set_attr "neg_pool_range" "*, *, *, *, *, 250, *, *, *, *, *") 219 (set_attr "length" "2, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4")] 220) 221 222;; SImode moves 223;; ??? For now do not allow loading constants into vfp regs. This causes 224;; problems because small constants get converted into adds. 225(define_insn "*arm_movsi_vfp" 226 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv") 227 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk,r,*t,*t,*Uvi,*t"))] 228 "TARGET_ARM && TARGET_HARD_FLOAT 229 && ( s_register_operand (operands[0], SImode) 230 || s_register_operand (operands[1], SImode))" 231 "* 232 switch (which_alternative) 233 { 234 case 0: case 1: 235 return \"mov%?\\t%0, %1\"; 236 case 2: 237 return \"mvn%?\\t%0, #%B1\"; 238 case 3: 239 return \"movw%?\\t%0, %1\"; 240 case 4: 241 return \"ldr%?\\t%0, %1\"; 242 case 5: 243 return \"str%?\\t%1, %0\"; 244 case 6: 245 return \"vmov%?\\t%0, %1\\t%@ int\"; 246 case 7: 247 return \"vmov%?\\t%0, %1\\t%@ int\"; 248 case 8: 249 return \"vmov%?.f32\\t%0, %1\\t%@ int\"; 250 case 9: case 10: 251 return output_move_vfp (operands); 252 default: 253 gcc_unreachable (); 254 } 255 " 256 [(set_attr "predicable" "yes") 257 (set_attr "type" "mov_reg,mov_reg,mvn_imm,mov_imm,load_4,store_4, 258 f_mcr,f_mrc,fmov,f_loads,f_stores") 259 (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*") 260 (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")] 261) 262 263;; See thumb2.md:thumb2_movsi_insn for an explanation of the split 264;; high/low register alternatives for loads and stores here. 265;; The l/Py alternative should come after r/I to ensure that the short variant 266;; is chosen with length 2 when the instruction is predicated for 267;; arm_restrict_it. 268(define_insn "*thumb2_movsi_vfp" 269 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r,l,*hk,m,*m,*t,\ 270 r,*t,*t,*Uv, Up, r,Uf,r") 271 (match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,*mi,l,*hk,r,*t,\ 272 *t,*UvTu,*t, r, Up,r,Uf"))] 273 "TARGET_THUMB2 && TARGET_VFP_BASE 274 && ( s_register_operand (operands[0], SImode) 275 || s_register_operand (operands[1], SImode))" 276 "* 277 switch (which_alternative) 278 { 279 case 0: 280 case 1: 281 case 2: 282 return \"mov%?\\t%0, %1\"; 283 case 3: 284 return \"mvn%?\\t%0, #%B1\"; 285 case 4: 286 return \"movw%?\\t%0, %1\"; 287 case 5: 288 case 6: 289 /* Cannot load it directly, split to load it via MOV / MOVT. */ 290 if (!MEM_P (operands[1]) && arm_disable_literal_pool) 291 return \"#\"; 292 return \"ldr%?\\t%0, %1\"; 293 case 7: 294 case 8: 295 return \"str%?\\t%1, %0\"; 296 case 9: 297 return \"vmov%?\\t%0, %1\\t%@ int\"; 298 case 10: 299 return \"vmov%?\\t%0, %1\\t%@ int\"; 300 case 11: 301 return \"vmov%?.f32\\t%0, %1\\t%@ int\"; 302 case 12: case 13: 303 return output_move_vfp (operands); 304 case 14: 305 return \"vmsr\\t P0, %1\"; 306 case 15: 307 return \"vmrs\\t %0, P0\"; 308 case 16: 309 return \"mcr\\tp10, 7, %1, cr1, cr0, 0\\t @SET_FPSCR\"; 310 case 17: 311 return \"mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR\"; 312 default: 313 gcc_unreachable (); 314 } 315 " 316 [(set_attr "predicable" "yes") 317 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,\ 318 no,no,no,no,no") 319 (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_imm,load_4,load_4,\ 320 store_4,store_4,f_mcr,f_mrc,fmov,f_loads,f_stores,mve_move,\ 321 mve_move,mrs,mrs") 322 (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4") 323 (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*,*,*,*,*") 324 (set_attr "arch" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,mve,mve,mve,mve") 325 (set_attr "neg_pool_range" "*,*,*,*,*, 0, 0,*,*,*,*,*,1008,*,*,*,*,*")] 326) 327 328 329;; DImode moves 330 331(define_insn "*movdi_vfp" 332 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,r,r,m,w,!r,w,w, Uv") 333 (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,r,r,w,w,UvTu,w"))] 334 "TARGET_32BIT && TARGET_VFP_BASE 335 && ( register_operand (operands[0], DImode) 336 || register_operand (operands[1], DImode)) 337 && !((TARGET_NEON || TARGET_HAVE_MVE) && CONST_INT_P (operands[1]) 338 && simd_immediate_valid_for_move (operands[1], DImode, NULL, NULL))" 339 "* 340 switch (which_alternative) 341 { 342 case 0: 343 case 1: 344 case 2: 345 case 3: 346 return \"#\"; 347 case 4: 348 case 5: 349 /* Cannot load it directly, split to load it via MOV / MOVT. */ 350 if (!MEM_P (operands[1]) && arm_disable_literal_pool) 351 return \"#\"; 352 /* Fall through. */ 353 case 6: 354 return output_move_double (operands, true, NULL); 355 case 7: 356 return \"vmov%?\\t%P0, %Q1, %R1\\t%@ int\"; 357 case 8: 358 return \"vmov%?\\t%Q0, %R0, %P1\\t%@ int\"; 359 case 9: 360 if (TARGET_VFP_SINGLE || TARGET_HAVE_MVE) 361 return \"vmov%?.f32\\t%0, %1\\t%@ int\;vmov%?.f32\\t%p0, %p1\\t%@ int\"; 362 else 363 return \"vmov%?.f64\\t%P0, %P1\\t%@ int\"; 364 case 10: case 11: 365 return output_move_vfp (operands); 366 default: 367 gcc_unreachable (); 368 } 369 " 370 [(set_attr "type" "multiple,multiple,multiple,multiple,load_8,load_8,store_8,f_mcrr,f_mrrc,ffarithd,f_loadd,f_stored") 371 (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8) 372 (eq_attr "alternative" "2") (const_int 12) 373 (eq_attr "alternative" "3") (const_int 16) 374 (eq_attr "alternative" "4,5,6") 375 (symbol_ref "arm_count_output_move_double_insns (operands) * 4") 376 (eq_attr "alternative" "9") 377 (if_then_else 378 (match_test "TARGET_VFP_SINGLE") 379 (const_int 8) 380 (const_int 4))] 381 (const_int 4))) 382 (set_attr "predicable" "yes") 383 (set_attr "arm_pool_range" "*,*,*,*,1020,4096,*,*,*,*,1020,*") 384 (set_attr "thumb2_pool_range" "*,*,*,*,1018,4094,*,*,*,*,1018,*") 385 (set_attr "neg_pool_range" "*,*,*,*,1004,0,*,*,*,*,1004,*") 386 (set (attr "ce_count") (symbol_ref "get_attr_length (insn) / 4")) 387 (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")] 388) 389 390;; HFmode and BFmode moves 391 392(define_insn "*mov<mode>_vfp_<mode>16" 393 [(set (match_operand:HFBF 0 "nonimmediate_operand" 394 "= ?r,?m,t,r,t,r,t, t, Uj,r") 395 (match_operand:HFBF 1 "general_operand" 396 " m,r,t,r,r,t,Dv,Uj,t, F"))] 397 "TARGET_32BIT 398 && (TARGET_VFP_FP16INST || TARGET_HAVE_MVE) 399 && (s_register_operand (operands[0], <MODE>mode) 400 || s_register_operand (operands[1], <MODE>mode))" 401 { 402 switch (which_alternative) 403 { 404 case 0: /* ARM register from memory. */ 405 return \"ldrh%?\\t%0, %1\\t%@ __<fporbf>\"; 406 case 1: /* Memory from ARM register. */ 407 return \"strh%?\\t%1, %0\\t%@ __<fporbf>\"; 408 case 2: /* S register from S register. */ 409 return \"vmov\\t%0, %1\t%@ __<fporbf>\"; 410 case 3: /* ARM register from ARM register. */ 411 return \"mov%?\\t%0, %1\\t%@ __<fporbf>\"; 412 case 4: /* S register from ARM register. */ 413 case 5: /* ARM register from S register. */ 414 case 6: /* S register from immediate. */ 415 return \"vmov.f16\\t%0, %1\t%@ __<fporbf>\"; 416 case 7: /* S register from memory. */ 417 if (TARGET_HAVE_MVE) 418 return \"vldr.16\\t%0, %1\"; 419 else 420 return \"vld1.16\\t{%z0}, %A1\"; 421 case 8: /* Memory from S register. */ 422 if (TARGET_HAVE_MVE) 423 return \"vstr.16\\t%1, %0\"; 424 else 425 return \"vst1.16\\t{%z1}, %A0\"; 426 case 9: /* ARM register from constant. */ 427 { 428 long bits; 429 rtx ops[4]; 430 431 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), 432 <MODE>mode); 433 ops[0] = operands[0]; 434 ops[1] = GEN_INT (bits); 435 ops[2] = GEN_INT (bits & 0xff00); 436 ops[3] = GEN_INT (bits & 0x00ff); 437 438 if (arm_arch_thumb2) 439 output_asm_insn (\"movw\\t%0, %1\", ops); 440 else 441 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops); 442 return \"\"; 443 } 444 default: 445 gcc_unreachable (); 446 } 447 } 448 [(set_attr "conds" "*, *, unconditional, *, unconditional, unconditional,\ 449 unconditional, unconditional, unconditional,\ 450 unconditional") 451 (set_attr "predicable" "yes, yes, no, yes, no, no, no, no, no, no") 452 (set_attr "predicable_short_it" "no, no, no, yes,\ 453 no, no, no, no,\ 454 no, no") 455 (set_attr_alternative "type" 456 [(const_string "load_4") (const_string "store_4") 457 (const_string "fmov") (const_string "mov_reg") 458 (const_string "f_mcr") (const_string "f_mrc") 459 (const_string "fconsts") (const_string "neon_load1_1reg") 460 (const_string "neon_store1_1reg") 461 (if_then_else (match_test "arm_arch_thumb2") 462 (const_string "mov_imm") 463 (const_string "multiple"))]) 464 (set_attr_alternative "length" 465 [(const_int 4) (const_int 4) 466 (const_int 4) (const_int 4) 467 (const_int 4) (const_int 4) 468 (const_int 4) (const_int 4) 469 (const_int 4) 470 (if_then_else (match_test "arm_arch_thumb2") 471 (const_int 4) 472 (const_int 8))])] 473) 474 475(define_insn "*mov<mode>_vfp_neon" 476 [(set (match_operand:HFBF 0 "nonimmediate_operand" "= t,Um,?r,?m,t,r,t,r,r") 477 (match_operand:HFBF 1 "general_operand" " Um, t, m, r,t,r,r,t,F"))] 478 "TARGET_32BIT 479 && TARGET_HARD_FLOAT && TARGET_NEON_FP16 480 && !TARGET_VFP_FP16INST 481 && ( s_register_operand (operands[0], <MODE>mode) 482 || s_register_operand (operands[1], <MODE>mode))" 483 "* 484 switch (which_alternative) 485 { 486 case 0: /* S register from memory */ 487 return \"vld1.16\\t{%z0}, %A1\"; 488 case 1: /* memory from S register */ 489 return \"vst1.16\\t{%z1}, %A0\"; 490 case 2: /* ARM register from memory */ 491 return \"ldrh\\t%0, %1\\t%@ __<fporbf>\"; 492 case 3: /* memory from ARM register */ 493 return \"strh\\t%1, %0\\t%@ __<fporbf>\"; 494 case 4: /* S register from S register */ 495 return \"vmov.f32\\t%0, %1\"; 496 case 5: /* ARM register from ARM register */ 497 return \"mov\\t%0, %1\\t%@ __<fporbf>\"; 498 case 6: /* S register from ARM register */ 499 return \"vmov\\t%0, %1\"; 500 case 7: /* ARM register from S register */ 501 return \"vmov\\t%0, %1\"; 502 case 8: /* ARM register from constant */ 503 { 504 long bits; 505 rtx ops[4]; 506 507 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), 508 <MODE>mode); 509 ops[0] = operands[0]; 510 ops[1] = GEN_INT (bits); 511 ops[2] = GEN_INT (bits & 0xff00); 512 ops[3] = GEN_INT (bits & 0x00ff); 513 514 if (arm_arch_thumb2) 515 output_asm_insn (\"movw\\t%0, %1\", ops); 516 else 517 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops); 518 return \"\"; 519 } 520 default: 521 gcc_unreachable (); 522 } 523 " 524 [(set_attr "conds" "unconditional") 525 (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\ 526 load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple") 527 (set_attr "length" "4,4,4,4,4,4,4,4,8")] 528) 529 530;; FP16 without element load/store instructions. 531(define_insn "*mov<mode>_vfp" 532 [(set (match_operand:HFBF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r") 533 (match_operand:HFBF 1 "general_operand" " m,r,t,r,r,t,F"))] 534 "TARGET_32BIT 535 && TARGET_HARD_FLOAT 536 && !TARGET_NEON_FP16 537 && !TARGET_VFP_FP16INST 538 && ( s_register_operand (operands[0], <MODE>mode) 539 || s_register_operand (operands[1], <MODE>mode))" 540 "* 541 switch (which_alternative) 542 { 543 case 0: /* ARM register from memory */ 544 return \"ldrh\\t%0, %1\\t%@ __<fporbf>\"; 545 case 1: /* memory from ARM register */ 546 return \"strh\\t%1, %0\\t%@ __<fporbf>\"; 547 case 2: /* S register from S register */ 548 return \"vmov.f32\\t%0, %1\"; 549 case 3: /* ARM register from ARM register */ 550 return \"mov\\t%0, %1\\t%@ __<fporbf>\"; 551 case 4: /* S register from ARM register */ 552 return \"vmov\\t%0, %1\"; 553 case 5: /* ARM register from S register */ 554 return \"vmov\\t%0, %1\"; 555 case 6: /* ARM register from constant */ 556 { 557 long bits; 558 rtx ops[4]; 559 560 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), 561 <MODE>mode); 562 ops[0] = operands[0]; 563 ops[1] = GEN_INT (bits); 564 ops[2] = GEN_INT (bits & 0xff00); 565 ops[3] = GEN_INT (bits & 0x00ff); 566 567 if (arm_arch_thumb2) 568 output_asm_insn (\"movw\\t%0, %1\", ops); 569 else 570 output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops); 571 return \"\"; 572 } 573 default: 574 gcc_unreachable (); 575 } 576 " 577 [(set_attr "conds" "unconditional") 578 (set_attr "type" "load_4,store_4,fmov,mov_reg,f_mcr,f_mrc,multiple") 579 (set_attr "length" "4,4,4,4,4,4,8")] 580) 581 582 583;; SFmode moves 584;; Disparage the w<->r cases because reloading an invalid address is 585;; preferable to loading the value via integer registers. 586 587(define_insn "*movsf_vfp" 588 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t ,Uv,r ,m,t,r") 589 (match_operand:SF 1 "general_operand" " ?r,t,Dv,UvE,t, mE,r,t,r"))] 590 "TARGET_ARM && TARGET_HARD_FLOAT 591 && ( s_register_operand (operands[0], SFmode) 592 || s_register_operand (operands[1], SFmode))" 593 "* 594 switch (which_alternative) 595 { 596 case 0: 597 return \"vmov%?\\t%0, %1\"; 598 case 1: 599 return \"vmov%?\\t%0, %1\"; 600 case 2: 601 return \"vmov%?.f32\\t%0, %1\"; 602 case 3: case 4: 603 return output_move_vfp (operands); 604 case 5: 605 return \"ldr%?\\t%0, %1\\t%@ float\"; 606 case 6: 607 return \"str%?\\t%1, %0\\t%@ float\"; 608 case 7: 609 return \"vmov%?.f32\\t%0, %1\"; 610 case 8: 611 return \"mov%?\\t%0, %1\\t%@ float\"; 612 default: 613 gcc_unreachable (); 614 } 615 " 616 [(set_attr "predicable" "yes") 617 (set_attr "type" 618 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg") 619 (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*") 620 (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")] 621) 622 623(define_insn "*thumb2_movsf_vfp" 624 [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t ,Uv,r ,m,t,r") 625 (match_operand:SF 1 "hard_sf_operand" " ?r,t,Dv,UvHa,t, mHa,r,t,r"))] 626 "TARGET_THUMB2 && TARGET_VFP_BASE 627 && ( s_register_operand (operands[0], SFmode) 628 || s_register_operand (operands[1], SFmode))" 629 "* 630 switch (which_alternative) 631 { 632 case 0: 633 return \"vmov%?\\t%0, %1\"; 634 case 1: 635 return \"vmov%?\\t%0, %1\"; 636 case 2: 637 return \"vmov%?.f32\\t%0, %1\"; 638 case 3: case 4: 639 return output_move_vfp (operands); 640 case 5: 641 return \"ldr%?\\t%0, %1\\t%@ float\"; 642 case 6: 643 return \"str%?\\t%1, %0\\t%@ float\"; 644 case 7: 645 return \"vmov%?.f32\\t%0, %1\"; 646 case 8: 647 return \"mov%?\\t%0, %1\\t%@ float\"; 648 default: 649 gcc_unreachable (); 650 } 651 " 652 [(set_attr "predicable" "yes") 653 (set_attr "type" 654 "f_mcr,f_mrc,fconsts,f_loads,f_stores,load_4,store_4,fmov,mov_reg") 655 (set_attr "pool_range" "*,*,*,1018,*,4090,*,*,*") 656 (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")] 657) 658 659;; DFmode moves 660 661(define_insn "*movdf_vfp" 662 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r, m,w,r") 663 (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,G,UvF,w ,mF,r,w,r"))] 664 "TARGET_ARM && TARGET_HARD_FLOAT 665 && ( register_operand (operands[0], DFmode) 666 || register_operand (operands[1], DFmode))" 667 "* 668 { 669 switch (which_alternative) 670 { 671 case 0: 672 return \"vmov%?\\t%P0, %Q1, %R1\"; 673 case 1: 674 return \"vmov%?\\t%Q0, %R0, %P1\"; 675 case 2: 676 gcc_assert (TARGET_VFP_DOUBLE); 677 return \"vmov%?.f64\\t%P0, %1\"; 678 case 3: 679 gcc_assert (TARGET_VFP_DOUBLE); 680 return \"vmov.i64\\t%P0, #0\\t%@ float\"; 681 case 4: case 5: 682 return output_move_vfp (operands); 683 case 6: case 7: 684 return output_move_double (operands, true, NULL); 685 case 8: 686 if (TARGET_VFP_SINGLE) 687 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\"; 688 else 689 return \"vmov%?.f64\\t%P0, %P1\"; 690 case 9: 691 return \"#\"; 692 default: 693 gcc_unreachable (); 694 } 695 } 696 " 697 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,f_stored,\ 698 load_8,store_8,ffarithd,multiple") 699 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8) 700 (eq_attr "alternative" "8") 701 (if_then_else 702 (match_test "TARGET_VFP_SINGLE") 703 (const_int 8) 704 (const_int 4))] 705 (const_int 4))) 706 (set_attr "predicable" "yes,yes,yes,no,yes,yes,yes,yes,yes,yes") 707 (set_attr "pool_range" "*,*,*,*,1020,*,1020,*,*,*") 708 (set_attr "neg_pool_range" "*,*,*,*,1004,*,1004,*,*,*") 709 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")] 710) 711 712(define_insn "*thumb2_movdf_vfp" 713 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w ,Uv,r ,m,w,r") 714 (match_operand:DF 1 "hard_df_operand" " ?r,w,Dy,G,UvHa,w, mHa,r, w,r"))] 715 "TARGET_THUMB2 && TARGET_VFP_BASE 716 && ( register_operand (operands[0], DFmode) 717 || register_operand (operands[1], DFmode))" 718 "* 719 { 720 switch (which_alternative) 721 { 722 case 0: 723 return \"vmov%?\\t%P0, %Q1, %R1\"; 724 case 1: 725 return \"vmov%?\\t%Q0, %R0, %P1\"; 726 case 2: 727 gcc_assert (TARGET_VFP_DOUBLE); 728 return \"vmov%?.f64\\t%P0, %1\"; 729 case 3: 730 gcc_assert (TARGET_VFP_DOUBLE); 731 return \"vmov.i64\\t%P0, #0\\t%@ float\"; 732 case 4: case 5: 733 return output_move_vfp (operands); 734 case 6: case 7: case 9: 735 return output_move_double (operands, true, NULL); 736 case 8: 737 if (TARGET_VFP_SINGLE) 738 return \"vmov%?.f32\\t%0, %1\;vmov%?.f32\\t%p0, %p1\"; 739 else 740 return \"vmov%?.f64\\t%P0, %P1\"; 741 default: 742 abort (); 743 } 744 } 745 " 746 [(set_attr "type" "f_mcrr,f_mrrc,fconstd,neon_move,f_loadd,\ 747 f_stored,load_8,store_8,ffarithd,multiple") 748 (set (attr "length") (cond [(eq_attr "alternative" "6,7,9") (const_int 8) 749 (eq_attr "alternative" "8") 750 (if_then_else 751 (match_test "TARGET_VFP_SINGLE") 752 (const_int 8) 753 (const_int 4))] 754 (const_int 4))) 755 (set_attr "pool_range" "*,*,*,*,1018,*,4094,*,*,*") 756 (set_attr "neg_pool_range" "*,*,*,*,1008,*,0,*,*,*") 757 (set_attr "arch" "any,any,any,neon,any,any,any,any,any,any")] 758) 759 760 761;; Conditional move patterns 762 763(define_insn "*movsfcc_vfp" 764 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r") 765 (if_then_else:SF 766 (match_operator 3 "arm_comparison_operator" 767 [(match_operand 4 "cc_register" "") (const_int 0)]) 768 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t") 769 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))] 770 "TARGET_ARM && TARGET_HARD_FLOAT" 771 "@ 772 vmov%D3.f32\\t%0, %2 773 vmov%d3.f32\\t%0, %1 774 vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1 775 vmov%D3\\t%0, %2 776 vmov%d3\\t%0, %1 777 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1 778 vmov%D3\\t%0, %2 779 vmov%d3\\t%0, %1 780 vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1" 781 [(set_attr "conds" "use") 782 (set_attr "length" "4,4,8,4,4,8,4,4,8") 783 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")] 784) 785 786(define_insn "*thumb2_movsfcc_vfp" 787 [(set (match_operand:SF 0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r") 788 (if_then_else:SF 789 (match_operator 3 "arm_comparison_operator" 790 [(match_operand 4 "cc_register" "") (const_int 0)]) 791 (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t") 792 (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))] 793 "TARGET_THUMB2 && TARGET_VFP_BASE && !arm_restrict_it" 794 "@ 795 it\\t%D3\;vmov%D3.f32\\t%0, %2 796 it\\t%d3\;vmov%d3.f32\\t%0, %1 797 ite\\t%D3\;vmov%D3.f32\\t%0, %2\;vmov%d3.f32\\t%0, %1 798 it\\t%D3\;vmov%D3\\t%0, %2 799 it\\t%d3\;vmov%d3\\t%0, %1 800 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1 801 it\\t%D3\;vmov%D3\\t%0, %2 802 it\\t%d3\;vmov%d3\\t%0, %1 803 ite\\t%D3\;vmov%D3\\t%0, %2\;vmov%d3\\t%0, %1" 804 [(set_attr "conds" "use") 805 (set_attr "length" "6,6,10,6,6,10,6,6,10") 806 (set_attr "type" "fmov,fmov,fmov,f_mcr,f_mcr,f_mcr,f_mrc,f_mrc,f_mrc")] 807) 808 809(define_insn "*movdfcc_vfp" 810 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r") 811 (if_then_else:DF 812 (match_operator 3 "arm_comparison_operator" 813 [(match_operand 4 "cc_register" "") (const_int 0)]) 814 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w") 815 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))] 816 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 817 "@ 818 vmov%D3.f64\\t%P0, %P2 819 vmov%d3.f64\\t%P0, %P1 820 vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1 821 vmov%D3\\t%P0, %Q2, %R2 822 vmov%d3\\t%P0, %Q1, %R1 823 vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1 824 vmov%D3\\t%Q0, %R0, %P2 825 vmov%d3\\t%Q0, %R0, %P1 826 vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1" 827 [(set_attr "conds" "use") 828 (set_attr "length" "4,4,8,4,4,8,4,4,8") 829 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcr,f_mrrc,f_mrrc,f_mrrc")] 830) 831 832(define_insn "*thumb2_movdfcc_vfp" 833 [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r") 834 (if_then_else:DF 835 (match_operator 3 "arm_comparison_operator" 836 [(match_operand 4 "cc_register" "") (const_int 0)]) 837 (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w") 838 (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))] 839 "TARGET_THUMB2 && TARGET_VFP_BASE && TARGET_VFP_DOUBLE 840 && !arm_restrict_it" 841 "@ 842 it\\t%D3\;vmov%D3.f64\\t%P0, %P2 843 it\\t%d3\;vmov%d3.f64\\t%P0, %P1 844 ite\\t%D3\;vmov%D3.f64\\t%P0, %P2\;vmov%d3.f64\\t%P0, %P1 845 it\t%D3\;vmov%D3\\t%P0, %Q2, %R2 846 it\t%d3\;vmov%d3\\t%P0, %Q1, %R1 847 ite\\t%D3\;vmov%D3\\t%P0, %Q2, %R2\;vmov%d3\\t%P0, %Q1, %R1 848 it\t%D3\;vmov%D3\\t%Q0, %R0, %P2 849 it\t%d3\;vmov%d3\\t%Q0, %R0, %P1 850 ite\\t%D3\;vmov%D3\\t%Q0, %R0, %P2\;vmov%d3\\t%Q0, %R0, %P1" 851 [(set_attr "conds" "use") 852 (set_attr "length" "6,6,10,6,6,10,6,6,10") 853 (set_attr "type" "ffarithd,ffarithd,ffarithd,f_mcr,f_mcr,f_mcrr,f_mrrc,f_mrrc,f_mrrc")] 854) 855 856 857;; Sign manipulation functions 858 859(define_insn "*abssf2_vfp" 860 [(set (match_operand:SF 0 "s_register_operand" "=t") 861 (abs:SF (match_operand:SF 1 "s_register_operand" "t")))] 862 "TARGET_32BIT && TARGET_HARD_FLOAT" 863 "vabs%?.f32\\t%0, %1" 864 [(set_attr "predicable" "yes") 865 (set_attr "type" "ffariths")] 866) 867 868(define_insn "*absdf2_vfp" 869 [(set (match_operand:DF 0 "s_register_operand" "=w") 870 (abs:DF (match_operand:DF 1 "s_register_operand" "w")))] 871 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 872 "vabs%?.f64\\t%P0, %P1" 873 [(set_attr "predicable" "yes") 874 (set_attr "type" "ffarithd")] 875) 876 877(define_insn "*negsf2_vfp" 878 [(set (match_operand:SF 0 "s_register_operand" "=t,?r") 879 (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))] 880 "TARGET_32BIT && TARGET_HARD_FLOAT" 881 "@ 882 vneg%?.f32\\t%0, %1 883 eor%?\\t%0, %1, #-2147483648" 884 [(set_attr "predicable" "yes") 885 (set_attr "type" "ffariths")] 886) 887 888(define_insn_and_split "*negdf2_vfp" 889 [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r") 890 (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))] 891 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 892 "@ 893 vneg%?.f64\\t%P0, %P1 894 # 895 #" 896 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed 897 && arm_general_register_operand (operands[0], DFmode)" 898 [(set (match_dup 0) (match_dup 1))] 899 " 900 if (REGNO (operands[0]) == REGNO (operands[1])) 901 { 902 operands[0] = gen_highpart (SImode, operands[0]); 903 operands[1] = gen_rtx_XOR (SImode, operands[0], 904 gen_int_mode (0x80000000, SImode)); 905 } 906 else 907 { 908 rtx in_hi, in_lo, out_hi, out_lo; 909 910 in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]), 911 gen_int_mode (0x80000000, SImode)); 912 in_lo = gen_lowpart (SImode, operands[1]); 913 out_hi = gen_highpart (SImode, operands[0]); 914 out_lo = gen_lowpart (SImode, operands[0]); 915 916 if (REGNO (in_lo) == REGNO (out_hi)) 917 { 918 emit_insn (gen_rtx_SET (out_lo, in_lo)); 919 operands[0] = out_hi; 920 operands[1] = in_hi; 921 } 922 else 923 { 924 emit_insn (gen_rtx_SET (out_hi, in_hi)); 925 operands[0] = out_lo; 926 operands[1] = in_lo; 927 } 928 } 929 " 930 [(set_attr "predicable" "yes") 931 (set_attr "length" "4,4,8") 932 (set_attr "type" "ffarithd")] 933) 934 935;; ABS and NEG for FP16. 936(define_insn "<absneg_str>hf2" 937 [(set (match_operand:HF 0 "s_register_operand" "=w") 938 (ABSNEG:HF (match_operand:HF 1 "s_register_operand" "w")))] 939 "TARGET_VFP_FP16INST" 940 "v<absneg_str>.f16\t%0, %1" 941 [(set_attr "conds" "unconditional") 942 (set_attr "type" "ffariths")] 943) 944 945(define_expand "neon_vabshf" 946 [(set 947 (match_operand:HF 0 "s_register_operand") 948 (abs:HF (match_operand:HF 1 "s_register_operand")))] 949 "TARGET_VFP_FP16INST" 950{ 951 emit_insn (gen_abshf2 (operands[0], operands[1])); 952 DONE; 953}) 954 955;; VRND for FP16. 956(define_insn "neon_v<fp16_rnd_str>hf" 957 [(set (match_operand:HF 0 "s_register_operand" "=w") 958 (unspec:HF 959 [(match_operand:HF 1 "s_register_operand" "w")] 960 FP16_RND))] 961 "TARGET_VFP_FP16INST" 962 "<fp16_rnd_insn>.f16\t%0, %1" 963 [(set_attr "conds" "unconditional") 964 (set_attr "type" "neon_fp_round_s")] 965) 966 967(define_insn "neon_vrndihf" 968 [(set (match_operand:HF 0 "s_register_operand" "=w") 969 (unspec:HF 970 [(match_operand:HF 1 "s_register_operand" "w")] 971 UNSPEC_VRNDI))] 972 "TARGET_VFP_FP16INST" 973 "vrintr.f16\t%0, %1" 974 [(set_attr "conds" "unconditional") 975 (set_attr "type" "neon_fp_round_s")] 976) 977 978;; Arithmetic insns 979 980(define_insn "addhf3" 981 [(set 982 (match_operand:HF 0 "s_register_operand" "=w") 983 (plus:HF 984 (match_operand:HF 1 "s_register_operand" "w") 985 (match_operand:HF 2 "s_register_operand" "w")))] 986 "TARGET_VFP_FP16INST" 987 "vadd.f16\t%0, %1, %2" 988 [(set_attr "conds" "unconditional") 989 (set_attr "type" "fadds")] 990) 991 992(define_insn "*addsf3_vfp" 993 [(set (match_operand:SF 0 "s_register_operand" "=t") 994 (plus:SF (match_operand:SF 1 "s_register_operand" "t") 995 (match_operand:SF 2 "s_register_operand" "t")))] 996 "TARGET_32BIT && TARGET_HARD_FLOAT" 997 "vadd%?.f32\\t%0, %1, %2" 998 [(set_attr "predicable" "yes") 999 (set_attr "type" "fadds")] 1000) 1001 1002(define_insn "*adddf3_vfp" 1003 [(set (match_operand:DF 0 "s_register_operand" "=w") 1004 (plus:DF (match_operand:DF 1 "s_register_operand" "w") 1005 (match_operand:DF 2 "s_register_operand" "w")))] 1006 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1007 "vadd%?.f64\\t%P0, %P1, %P2" 1008 [(set_attr "predicable" "yes") 1009 (set_attr "type" "faddd")] 1010) 1011 1012(define_insn "subhf3" 1013 [(set 1014 (match_operand:HF 0 "s_register_operand" "=w") 1015 (minus:HF 1016 (match_operand:HF 1 "s_register_operand" "w") 1017 (match_operand:HF 2 "s_register_operand" "w")))] 1018 "TARGET_VFP_FP16INST" 1019 "vsub.f16\t%0, %1, %2" 1020 [(set_attr "conds" "unconditional") 1021 (set_attr "type" "fadds")] 1022) 1023 1024(define_insn "*subsf3_vfp" 1025 [(set (match_operand:SF 0 "s_register_operand" "=t") 1026 (minus:SF (match_operand:SF 1 "s_register_operand" "t") 1027 (match_operand:SF 2 "s_register_operand" "t")))] 1028 "TARGET_32BIT && TARGET_HARD_FLOAT" 1029 "vsub%?.f32\\t%0, %1, %2" 1030 [(set_attr "predicable" "yes") 1031 (set_attr "type" "fadds")] 1032) 1033 1034(define_insn "*subdf3_vfp" 1035 [(set (match_operand:DF 0 "s_register_operand" "=w") 1036 (minus:DF (match_operand:DF 1 "s_register_operand" "w") 1037 (match_operand:DF 2 "s_register_operand" "w")))] 1038 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1039 "vsub%?.f64\\t%P0, %P1, %P2" 1040 [(set_attr "predicable" "yes") 1041 (set_attr "type" "faddd")] 1042) 1043 1044 1045;; Division insns 1046 1047;; FP16 Division. 1048(define_insn "divhf3" 1049 [(set 1050 (match_operand:HF 0 "s_register_operand" "=w") 1051 (div:HF 1052 (match_operand:HF 1 "s_register_operand" "w") 1053 (match_operand:HF 2 "s_register_operand" "w")))] 1054 "TARGET_VFP_FP16INST" 1055 "vdiv.f16\t%0, %1, %2" 1056 [(set_attr "conds" "unconditional") 1057 (set_attr "type" "fdivs")] 1058) 1059 1060; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input 1061; operands, so mark the output as early clobber for VFPv2 on ARMv5 or 1062; earlier. 1063(define_insn "*divsf3_vfp" 1064 [(set (match_operand:SF 0 "s_register_operand" "=&t,t") 1065 (div:SF (match_operand:SF 1 "s_register_operand" "t,t") 1066 (match_operand:SF 2 "s_register_operand" "t,t")))] 1067 "TARGET_32BIT && TARGET_HARD_FLOAT" 1068 "vdiv%?.f32\\t%0, %1, %2" 1069 [(set_attr "predicable" "yes") 1070 (set_attr "arch" "*,armv6_or_vfpv3") 1071 (set_attr "type" "fdivs")] 1072) 1073 1074(define_insn "*divdf3_vfp" 1075 [(set (match_operand:DF 0 "s_register_operand" "=&w,w") 1076 (div:DF (match_operand:DF 1 "s_register_operand" "w,w") 1077 (match_operand:DF 2 "s_register_operand" "w,w")))] 1078 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1079 "vdiv%?.f64\\t%P0, %P1, %P2" 1080 [(set_attr "predicable" "yes") 1081 (set_attr "arch" "*,armv6_or_vfpv3") 1082 (set_attr "type" "fdivd")] 1083) 1084 1085 1086;; Multiplication insns 1087 1088(define_insn "mulhf3" 1089 [(set 1090 (match_operand:HF 0 "s_register_operand" "=w") 1091 (mult:HF (match_operand:HF 1 "s_register_operand" "w") 1092 (match_operand:HF 2 "s_register_operand" "w")))] 1093 "TARGET_VFP_FP16INST" 1094 "vmul.f16\t%0, %1, %2" 1095 [(set_attr "conds" "unconditional") 1096 (set_attr "type" "fmuls")] 1097) 1098 1099(define_insn "*mulsf3_vfp" 1100 [(set (match_operand:SF 0 "s_register_operand" "=t") 1101 (mult:SF (match_operand:SF 1 "s_register_operand" "t") 1102 (match_operand:SF 2 "s_register_operand" "t")))] 1103 "TARGET_32BIT && TARGET_HARD_FLOAT" 1104 "vmul%?.f32\\t%0, %1, %2" 1105 [(set_attr "predicable" "yes") 1106 (set_attr "type" "fmuls")] 1107) 1108 1109(define_insn "*muldf3_vfp" 1110 [(set (match_operand:DF 0 "s_register_operand" "=w") 1111 (mult:DF (match_operand:DF 1 "s_register_operand" "w") 1112 (match_operand:DF 2 "s_register_operand" "w")))] 1113 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1114 "vmul%?.f64\\t%P0, %P1, %P2" 1115 [(set_attr "predicable" "yes") 1116 (set_attr "type" "fmuld")] 1117) 1118 1119(define_insn "*mulsf3neghf_vfp" 1120 [(set (match_operand:HF 0 "s_register_operand" "=t") 1121 (mult:HF (neg:HF (match_operand:HF 1 "s_register_operand" "t")) 1122 (match_operand:HF 2 "s_register_operand" "t")))] 1123 "TARGET_VFP_FP16INST && !flag_rounding_math" 1124 "vnmul.f16\\t%0, %1, %2" 1125 [(set_attr "conds" "unconditional") 1126 (set_attr "type" "fmuls")] 1127) 1128 1129(define_insn "*negmulhf3_vfp" 1130 [(set (match_operand:HF 0 "s_register_operand" "=t") 1131 (neg:HF (mult:HF (match_operand:HF 1 "s_register_operand" "t") 1132 (match_operand:HF 2 "s_register_operand" "t"))))] 1133 "TARGET_VFP_FP16INST" 1134 "vnmul.f16\\t%0, %1, %2" 1135 [(set_attr "conds" "unconditional") 1136 (set_attr "type" "fmuls")] 1137) 1138 1139(define_insn "*mulsf3negsf_vfp" 1140 [(set (match_operand:SF 0 "s_register_operand" "=t") 1141 (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t")) 1142 (match_operand:SF 2 "s_register_operand" "t")))] 1143 "TARGET_32BIT && TARGET_HARD_FLOAT && !flag_rounding_math" 1144 "vnmul%?.f32\\t%0, %1, %2" 1145 [(set_attr "predicable" "yes") 1146 (set_attr "type" "fmuls")] 1147) 1148 1149(define_insn "*negmulsf3_vfp" 1150 [(set (match_operand:SF 0 "s_register_operand" "=t") 1151 (neg:SF (mult:SF (match_operand:SF 1 "s_register_operand" "t") 1152 (match_operand:SF 2 "s_register_operand" "t"))))] 1153 "TARGET_32BIT && TARGET_HARD_FLOAT" 1154 "vnmul%?.f32\\t%0, %1, %2" 1155 [(set_attr "predicable" "yes") 1156 (set_attr "type" "fmuls")] 1157) 1158 1159(define_insn "*muldf3negdf_vfp" 1160 [(set (match_operand:DF 0 "s_register_operand" "=w") 1161 (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w")) 1162 (match_operand:DF 2 "s_register_operand" "w")))] 1163 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE 1164 && !flag_rounding_math" 1165 "vnmul%?.f64\\t%P0, %P1, %P2" 1166 [(set_attr "predicable" "yes") 1167 (set_attr "type" "fmuld")] 1168) 1169 1170(define_insn "*negmuldf3_vfp" 1171 [(set (match_operand:DF 0 "s_register_operand" "=w") 1172 (neg:DF (mult:DF (match_operand:DF 1 "s_register_operand" "w") 1173 (match_operand:DF 2 "s_register_operand" "w"))))] 1174 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1175 "vnmul%?.f64\\t%P0, %P1, %P2" 1176 [(set_attr "predicable" "yes") 1177 (set_attr "type" "fmuld")] 1178) 1179 1180 1181;; Multiply-accumulate insns 1182 1183;; 0 = 1 * 2 + 0 1184(define_insn "*mulsf3addhf_vfp" 1185 [(set (match_operand:HF 0 "s_register_operand" "=t") 1186 (plus:HF 1187 (mult:HF (match_operand:HF 2 "s_register_operand" "t") 1188 (match_operand:HF 3 "s_register_operand" "t")) 1189 (match_operand:HF 1 "s_register_operand" "0")))] 1190 "TARGET_VFP_FP16INST" 1191 "vmla.f16\\t%0, %2, %3" 1192 [(set_attr "conds" "unconditional") 1193 (set_attr "type" "fmacs")] 1194) 1195 1196(define_insn "*mulsf3addsf_vfp" 1197 [(set (match_operand:SF 0 "s_register_operand" "=t") 1198 (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t") 1199 (match_operand:SF 3 "s_register_operand" "t")) 1200 (match_operand:SF 1 "s_register_operand" "0")))] 1201 "TARGET_32BIT && TARGET_HARD_FLOAT" 1202 "vmla%?.f32\\t%0, %2, %3" 1203 [(set_attr "predicable" "yes") 1204 (set_attr "type" "fmacs")] 1205) 1206 1207(define_insn "*muldf3adddf_vfp" 1208 [(set (match_operand:DF 0 "s_register_operand" "=w") 1209 (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w") 1210 (match_operand:DF 3 "s_register_operand" "w")) 1211 (match_operand:DF 1 "s_register_operand" "0")))] 1212 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1213 "vmla%?.f64\\t%P0, %P2, %P3" 1214 [(set_attr "predicable" "yes") 1215 (set_attr "type" "fmacd")] 1216) 1217 1218;; 0 = 1 * 2 - 0 1219(define_insn "*mulhf3subhf_vfp" 1220 [(set (match_operand:HF 0 "s_register_operand" "=t") 1221 (minus:HF (mult:HF (match_operand:HF 2 "s_register_operand" "t") 1222 (match_operand:HF 3 "s_register_operand" "t")) 1223 (match_operand:HF 1 "s_register_operand" "0")))] 1224 "TARGET_VFP_FP16INST" 1225 "vnmls.f16\\t%0, %2, %3" 1226 [(set_attr "conds" "unconditional") 1227 (set_attr "type" "fmacs")] 1228) 1229 1230(define_insn "*mulsf3subsf_vfp" 1231 [(set (match_operand:SF 0 "s_register_operand" "=t") 1232 (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t") 1233 (match_operand:SF 3 "s_register_operand" "t")) 1234 (match_operand:SF 1 "s_register_operand" "0")))] 1235 "TARGET_32BIT && TARGET_HARD_FLOAT" 1236 "vnmls%?.f32\\t%0, %2, %3" 1237 [(set_attr "predicable" "yes") 1238 (set_attr "type" "fmacs")] 1239) 1240 1241(define_insn "*muldf3subdf_vfp" 1242 [(set (match_operand:DF 0 "s_register_operand" "=w") 1243 (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w") 1244 (match_operand:DF 3 "s_register_operand" "w")) 1245 (match_operand:DF 1 "s_register_operand" "0")))] 1246 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1247 "vnmls%?.f64\\t%P0, %P2, %P3" 1248 [(set_attr "predicable" "yes") 1249 (set_attr "type" "fmacd")] 1250) 1251 1252;; 0 = -(1 * 2) + 0 1253(define_insn "*mulhf3neghfaddhf_vfp" 1254 [(set (match_operand:HF 0 "s_register_operand" "=t") 1255 (minus:HF (match_operand:HF 1 "s_register_operand" "0") 1256 (mult:HF (match_operand:HF 2 "s_register_operand" "t") 1257 (match_operand:HF 3 "s_register_operand" "t"))))] 1258 "TARGET_VFP_FP16INST" 1259 "vmls.f16\\t%0, %2, %3" 1260 [(set_attr "conds" "unconditional") 1261 (set_attr "type" "fmacs")] 1262) 1263 1264(define_insn "*mulsf3negsfaddsf_vfp" 1265 [(set (match_operand:SF 0 "s_register_operand" "=t") 1266 (minus:SF (match_operand:SF 1 "s_register_operand" "0") 1267 (mult:SF (match_operand:SF 2 "s_register_operand" "t") 1268 (match_operand:SF 3 "s_register_operand" "t"))))] 1269 "TARGET_32BIT && TARGET_HARD_FLOAT" 1270 "vmls%?.f32\\t%0, %2, %3" 1271 [(set_attr "predicable" "yes") 1272 (set_attr "type" "fmacs")] 1273) 1274 1275(define_insn "*fmuldf3negdfadddf_vfp" 1276 [(set (match_operand:DF 0 "s_register_operand" "=w") 1277 (minus:DF (match_operand:DF 1 "s_register_operand" "0") 1278 (mult:DF (match_operand:DF 2 "s_register_operand" "w") 1279 (match_operand:DF 3 "s_register_operand" "w"))))] 1280 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1281 "vmls%?.f64\\t%P0, %P2, %P3" 1282 [(set_attr "predicable" "yes") 1283 (set_attr "type" "fmacd")] 1284) 1285 1286 1287;; 0 = -(1 * 2) - 0 1288(define_insn "*mulhf3neghfsubhf_vfp" 1289 [(set (match_operand:HF 0 "s_register_operand" "=t") 1290 (minus:HF (mult:HF 1291 (neg:HF (match_operand:HF 2 "s_register_operand" "t")) 1292 (match_operand:HF 3 "s_register_operand" "t")) 1293 (match_operand:HF 1 "s_register_operand" "0")))] 1294 "TARGET_VFP_FP16INST" 1295 "vnmla.f16\\t%0, %2, %3" 1296 [(set_attr "conds" "unconditional") 1297 (set_attr "type" "fmacs")] 1298) 1299 1300(define_insn "*mulsf3negsfsubsf_vfp" 1301 [(set (match_operand:SF 0 "s_register_operand" "=t") 1302 (minus:SF (mult:SF 1303 (neg:SF (match_operand:SF 2 "s_register_operand" "t")) 1304 (match_operand:SF 3 "s_register_operand" "t")) 1305 (match_operand:SF 1 "s_register_operand" "0")))] 1306 "TARGET_32BIT && TARGET_HARD_FLOAT" 1307 "vnmla%?.f32\\t%0, %2, %3" 1308 [(set_attr "predicable" "yes") 1309 (set_attr "type" "fmacs")] 1310) 1311 1312(define_insn "*muldf3negdfsubdf_vfp" 1313 [(set (match_operand:DF 0 "s_register_operand" "=w") 1314 (minus:DF (mult:DF 1315 (neg:DF (match_operand:DF 2 "s_register_operand" "w")) 1316 (match_operand:DF 3 "s_register_operand" "w")) 1317 (match_operand:DF 1 "s_register_operand" "0")))] 1318 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1319 "vnmla%?.f64\\t%P0, %P2, %P3" 1320 [(set_attr "predicable" "yes") 1321 (set_attr "type" "fmacd")] 1322) 1323 1324;; Fused-multiply-accumulate 1325 1326(define_insn "fmahf4" 1327 [(set (match_operand:HF 0 "register_operand" "=w") 1328 (fma:HF 1329 (match_operand:HF 1 "register_operand" "w") 1330 (match_operand:HF 2 "register_operand" "w") 1331 (match_operand:HF 3 "register_operand" "0")))] 1332 "TARGET_VFP_FP16INST" 1333 "vfma.f16\\t%0, %1, %2" 1334 [(set_attr "conds" "unconditional") 1335 (set_attr "type" "ffmas")] 1336) 1337 1338(define_expand "neon_vfmahf" 1339 [(match_operand:HF 0 "s_register_operand") 1340 (match_operand:HF 1 "s_register_operand") 1341 (match_operand:HF 2 "s_register_operand") 1342 (match_operand:HF 3 "s_register_operand")] 1343 "TARGET_VFP_FP16INST" 1344{ 1345 emit_insn (gen_fmahf4 (operands[0], operands[2], operands[3], 1346 operands[1])); 1347 DONE; 1348}) 1349 1350(define_insn "fma<SDF:mode>4" 1351 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") 1352 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") 1353 (match_operand:SDF 2 "register_operand" "<F_constraint>") 1354 (match_operand:SDF 3 "register_operand" "0")))] 1355 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>" 1356 "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1357 [(set_attr "predicable" "yes") 1358 (set_attr "type" "ffma<vfp_type>")] 1359) 1360 1361(define_insn "fmsubhf4_fp16" 1362 [(set (match_operand:HF 0 "register_operand" "=w") 1363 (fma:HF 1364 (neg:HF (match_operand:HF 1 "register_operand" "w")) 1365 (match_operand:HF 2 "register_operand" "w") 1366 (match_operand:HF 3 "register_operand" "0")))] 1367 "TARGET_VFP_FP16INST" 1368 "vfms.f16\\t%0, %1, %2" 1369 [(set_attr "conds" "unconditional") 1370 (set_attr "type" "ffmas")] 1371) 1372 1373(define_expand "neon_vfmshf" 1374 [(match_operand:HF 0 "s_register_operand") 1375 (match_operand:HF 1 "s_register_operand") 1376 (match_operand:HF 2 "s_register_operand") 1377 (match_operand:HF 3 "s_register_operand")] 1378 "TARGET_VFP_FP16INST" 1379{ 1380 emit_insn (gen_fmsubhf4_fp16 (operands[0], operands[2], operands[3], 1381 operands[1])); 1382 DONE; 1383}) 1384 1385(define_insn "*fmsub<SDF:mode>4" 1386 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") 1387 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand" 1388 "<F_constraint>")) 1389 (match_operand:SDF 2 "register_operand" "<F_constraint>") 1390 (match_operand:SDF 3 "register_operand" "0")))] 1391 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>" 1392 "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1393 [(set_attr "predicable" "yes") 1394 (set_attr "type" "ffma<vfp_type>")] 1395) 1396 1397(define_insn "*fnmsubhf4" 1398 [(set (match_operand:HF 0 "register_operand" "=w") 1399 (fma:HF (match_operand:HF 1 "register_operand" "w") 1400 (match_operand:HF 2 "register_operand" "w") 1401 (neg:HF (match_operand:HF 3 "register_operand" "0"))))] 1402 "TARGET_VFP_FP16INST" 1403 "vfnms.f16\\t%0, %1, %2" 1404 [(set_attr "conds" "unconditional") 1405 (set_attr "type" "ffmas")] 1406) 1407 1408(define_insn "*fnmsub<SDF:mode>4" 1409 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") 1410 (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") 1411 (match_operand:SDF 2 "register_operand" "<F_constraint>") 1412 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))] 1413 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>" 1414 "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1415 [(set_attr "predicable" "yes") 1416 (set_attr "type" "ffma<vfp_type>")] 1417) 1418 1419(define_insn "*fnmaddhf4" 1420 [(set (match_operand:HF 0 "register_operand" "=w") 1421 (fma:HF (neg:HF (match_operand:HF 1 "register_operand" "w")) 1422 (match_operand:HF 2 "register_operand" "w") 1423 (neg:HF (match_operand:HF 3 "register_operand" "0"))))] 1424 "TARGET_VFP_FP16INST" 1425 "vfnma.f16\\t%0, %1, %2" 1426 [(set_attr "conds" "unconditional") 1427 (set_attr "type" "ffmas")] 1428) 1429 1430(define_insn "*fnmadd<SDF:mode>4" 1431 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") 1432 (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand" 1433 "<F_constraint>")) 1434 (match_operand:SDF 2 "register_operand" "<F_constraint>") 1435 (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))] 1436 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>" 1437 "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1438 [(set_attr "predicable" "yes") 1439 (set_attr "type" "ffma<vfp_type>")] 1440) 1441 1442 1443;; Conversion routines 1444 1445(define_insn "*extendsfdf2_vfp" 1446 [(set (match_operand:DF 0 "s_register_operand" "=w") 1447 (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))] 1448 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1449 "vcvt%?.f64.f32\\t%P0, %1" 1450 [(set_attr "predicable" "yes") 1451 (set_attr "type" "f_cvt")] 1452) 1453 1454(define_insn "*truncdfsf2_vfp" 1455 [(set (match_operand:SF 0 "s_register_operand" "=t") 1456 (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))] 1457 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1458 "vcvt%?.f32.f64\\t%0, %P1" 1459 [(set_attr "predicable" "yes") 1460 (set_attr "type" "f_cvt")] 1461) 1462 1463(define_insn "extendhfsf2" 1464 [(set (match_operand:SF 0 "s_register_operand" "=t") 1465 (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))] 1466 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)" 1467 "vcvtb%?.f32.f16\\t%0, %1" 1468 [(set_attr "predicable" "yes") 1469 (set_attr "type" "f_cvt")] 1470) 1471 1472(define_insn "*truncdfhf2" 1473 [(set (match_operand:HF 0 "s_register_operand" "=t") 1474 (float_truncate:HF (match_operand:DF 1 "s_register_operand" "w")))] 1475 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE" 1476 "vcvtb%?.f16.f64\\t%0, %P1" 1477 [(set_attr "predicable" "yes") 1478 (set_attr "type" "f_cvt")] 1479) 1480 1481(define_insn "*extendhfdf2" 1482 [(set (match_operand:DF 0 "s_register_operand" "=w") 1483 (float_extend:DF (match_operand:HF 1 "s_register_operand" "t")))] 1484 "TARGET_32BIT && TARGET_FP16_TO_DOUBLE" 1485 "vcvtb%?.f64.f16\\t%P0, %1" 1486 [(set_attr "predicable" "yes") 1487 (set_attr "type" "f_cvt")] 1488) 1489 1490(define_insn "truncsfhf2" 1491 [(set (match_operand:HF 0 "s_register_operand" "=t") 1492 (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))] 1493 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FP16 || TARGET_VFP_FP16INST)" 1494 "vcvtb%?.f16.f32\\t%0, %1" 1495 [(set_attr "predicable" "yes") 1496 (set_attr "type" "f_cvt")] 1497) 1498 1499(define_insn "*truncsisf2_vfp" 1500 [(set (match_operand:SI 0 "s_register_operand" "=t") 1501 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))] 1502 "TARGET_32BIT && TARGET_HARD_FLOAT" 1503 "vcvt%?.s32.f32\\t%0, %1" 1504 [(set_attr "predicable" "yes") 1505 (set_attr "type" "f_cvtf2i")] 1506) 1507 1508(define_insn "*truncsidf2_vfp" 1509 [(set (match_operand:SI 0 "s_register_operand" "=t") 1510 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))] 1511 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1512 "vcvt%?.s32.f64\\t%0, %P1" 1513 [(set_attr "predicable" "yes") 1514 (set_attr "type" "f_cvtf2i")] 1515) 1516 1517 1518(define_insn "fixuns_truncsfsi2" 1519 [(set (match_operand:SI 0 "s_register_operand" "=t") 1520 (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))] 1521 "TARGET_32BIT && TARGET_HARD_FLOAT" 1522 "vcvt%?.u32.f32\\t%0, %1" 1523 [(set_attr "predicable" "yes") 1524 (set_attr "type" "f_cvtf2i")] 1525) 1526 1527(define_insn "fixuns_truncdfsi2" 1528 [(set (match_operand:SI 0 "s_register_operand" "=t") 1529 (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))] 1530 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1531 "vcvt%?.u32.f64\\t%0, %P1" 1532 [(set_attr "predicable" "yes") 1533 (set_attr "type" "f_cvtf2i")] 1534) 1535 1536 1537(define_insn "*floatsisf2_vfp" 1538 [(set (match_operand:SF 0 "s_register_operand" "=t") 1539 (float:SF (match_operand:SI 1 "s_register_operand" "t")))] 1540 "TARGET_32BIT && TARGET_HARD_FLOAT" 1541 "vcvt%?.f32.s32\\t%0, %1" 1542 [(set_attr "predicable" "yes") 1543 (set_attr "type" "f_cvti2f")] 1544) 1545 1546(define_insn "*floatsidf2_vfp" 1547 [(set (match_operand:DF 0 "s_register_operand" "=w") 1548 (float:DF (match_operand:SI 1 "s_register_operand" "t")))] 1549 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1550 "vcvt%?.f64.s32\\t%P0, %1" 1551 [(set_attr "predicable" "yes") 1552 (set_attr "type" "f_cvti2f")] 1553) 1554 1555 1556(define_insn "floatunssisf2" 1557 [(set (match_operand:SF 0 "s_register_operand" "=t") 1558 (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))] 1559 "TARGET_32BIT && TARGET_HARD_FLOAT" 1560 "vcvt%?.f32.u32\\t%0, %1" 1561 [(set_attr "predicable" "yes") 1562 (set_attr "type" "f_cvti2f")] 1563) 1564 1565(define_insn "floatunssidf2" 1566 [(set (match_operand:DF 0 "s_register_operand" "=w") 1567 (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))] 1568 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1569 "vcvt%?.f64.u32\\t%P0, %1" 1570 [(set_attr "predicable" "yes") 1571 (set_attr "type" "f_cvti2f")] 1572) 1573 1574 1575;; Sqrt insns. 1576 1577(define_insn "neon_vsqrthf" 1578 [(set (match_operand:HF 0 "s_register_operand" "=w") 1579 (sqrt:HF (match_operand:HF 1 "s_register_operand" "w")))] 1580 "TARGET_VFP_FP16INST" 1581 "vsqrt.f16\t%0, %1" 1582 [(set_attr "conds" "unconditional") 1583 (set_attr "type" "fsqrts")] 1584) 1585 1586(define_insn "neon_vrsqrtshf" 1587 [(set 1588 (match_operand:HF 0 "s_register_operand" "=w") 1589 (unspec:HF [(match_operand:HF 1 "s_register_operand" "w") 1590 (match_operand:HF 2 "s_register_operand" "w")] 1591 UNSPEC_VRSQRTS))] 1592 "TARGET_VFP_FP16INST" 1593 "vrsqrts.f16\t%0, %1, %2" 1594 [(set_attr "conds" "unconditional") 1595 (set_attr "type" "fsqrts")] 1596) 1597 1598; VFP9 Erratum 760019: It's potentially unsafe to overwrite the input 1599; operands, so mark the output as early clobber for VFPv2 on ARMv5 or 1600; earlier. 1601(define_insn "*sqrtsf2_vfp" 1602 [(set (match_operand:SF 0 "s_register_operand" "=&t,t") 1603 (sqrt:SF (match_operand:SF 1 "s_register_operand" "t,t")))] 1604 "TARGET_32BIT && TARGET_HARD_FLOAT" 1605 "vsqrt%?.f32\\t%0, %1" 1606 [(set_attr "predicable" "yes") 1607 (set_attr "arch" "*,armv6_or_vfpv3") 1608 (set_attr "type" "fsqrts")] 1609) 1610 1611(define_insn "*sqrtdf2_vfp" 1612 [(set (match_operand:DF 0 "s_register_operand" "=&w,w") 1613 (sqrt:DF (match_operand:DF 1 "s_register_operand" "w,w")))] 1614 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1615 "vsqrt%?.f64\\t%P0, %P1" 1616 [(set_attr "predicable" "yes") 1617 (set_attr "arch" "*,armv6_or_vfpv3") 1618 (set_attr "type" "fsqrtd")] 1619) 1620 1621 1622;; Patterns to split/copy vfp condition flags. 1623 1624(define_insn "*movcc_vfp" 1625 [(set (reg CC_REGNUM) 1626 (reg VFPCC_REGNUM))] 1627 "TARGET_32BIT && TARGET_HARD_FLOAT" 1628 "vmrs%?\\tAPSR_nzcv, FPSCR" 1629 [(set_attr "conds" "set") 1630 (set_attr "type" "f_flag")] 1631) 1632 1633(define_insn "push_fpsysreg_insn" 1634 [(set (mem:SI (post_dec:SI (match_operand:SI 0 "s_register_operand" "+&rk"))) 1635 (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "n")] 1636 VUNSPEC_VSTR_VLDR))] 1637 "TARGET_HAVE_FPCXT_CMSE && use_cmse" 1638 { 1639 static char buf[32]; 1640 int fp_sysreg_enum = INTVAL (operands[1]); 1641 1642 gcc_assert (IN_RANGE (fp_sysreg_enum, 0, NB_FP_SYSREGS - 1)); 1643 1644 snprintf (buf, sizeof (buf), \"vstr%%?\\t%s, [%%0, #-4]!\", 1645 fp_sysreg_names[fp_sysreg_enum]); 1646 return buf; 1647 } 1648 [(set_attr "predicable" "yes") 1649 (set_attr "type" "store_4")] 1650) 1651 1652(define_insn "pop_fpsysreg_insn" 1653 [(set (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+&rk"))) 1654 (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "n")] 1655 VUNSPEC_VSTR_VLDR))] 1656 "TARGET_HAVE_FPCXT_CMSE && use_cmse" 1657 { 1658 static char buf[32]; 1659 int fp_sysreg_enum = INTVAL (operands[1]); 1660 1661 gcc_assert (IN_RANGE (fp_sysreg_enum, 0, NB_FP_SYSREGS - 1)); 1662 1663 snprintf (buf, sizeof (buf), \"vldr%%?\\t%s, [%%0], #4\", 1664 fp_sysreg_names[fp_sysreg_enum]); 1665 return buf; 1666 } 1667 [(set_attr "predicable" "yes") 1668 (set_attr "type" "load_4")] 1669) 1670 1671;; The operands are validated through the clear_multiple_operation 1672;; match_parallel predicate rather than through constraints so enable it only 1673;; after reload. 1674(define_insn "*clear_vfp_multiple" 1675 [(match_parallel 0 "clear_vfp_multiple_operation" 1676 [(unspec_volatile [(const_int 0)] 1677 VUNSPEC_VSCCLRM_VPR)])] 1678 "TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed" 1679 { 1680 int num_regs = XVECLEN (operands[0], 0); 1681 char pattern[30]; 1682 rtx reg; 1683 1684 strcpy (pattern, \"vscclrm%?\\t{%|\"); 1685 if (num_regs > 1) 1686 { 1687 reg = XEXP (XVECEXP (operands[0], 0, 1), 0); 1688 strcat (pattern, reg_names[REGNO (reg)]); 1689 if (num_regs > 2) 1690 { 1691 strcat (pattern, \"-%|\"); 1692 reg = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0); 1693 strcat (pattern, reg_names[REGNO (reg)]); 1694 } 1695 strcat (pattern, \", \"); 1696 } 1697 1698 strcat (pattern, \"VPR}\"); 1699 output_asm_insn (pattern, operands); 1700 return \"\"; 1701 } 1702 [(set_attr "predicable" "yes") 1703 (set_attr "type" "mov_reg")] 1704) 1705 1706;; Both this and the next instruction are treated by GCC in the same 1707;; way as a blockage pattern. That's perhaps stronger than it needs 1708;; to be, but we do not want accesses to the VFP register bank to be 1709;; moved across either instruction. 1710 1711(define_insn "lazy_store_multiple_insn" 1712 [(unspec_volatile 1713 [(mem:BLK (match_operand:SI 0 "s_register_operand" "rk"))] 1714 VUNSPEC_VLSTM)] 1715 "use_cmse && reload_completed" 1716 "vlstm%?\\t%0" 1717 [(set_attr "predicable" "yes") 1718 (set_attr "type" "store_4")] 1719) 1720 1721(define_insn "lazy_load_multiple_insn" 1722 [(unspec_volatile 1723 [(mem:BLK (match_operand:SI 0 "s_register_operand" "rk,rk"))] 1724 VUNSPEC_VLLDM)] 1725 "use_cmse && reload_completed" 1726 "@ 1727 vscclrm\\t{vpr}\;vlldm\\t%0 1728 vlldm\\t%0" 1729 [(set_attr "arch" "fix_vlldm,*") 1730 (set_attr "predicable" "no") 1731 (set_attr "length" "8,4") 1732 (set_attr "type" "load_4")] 1733) 1734 1735(define_insn_and_split "*cmpsf_split_vfp" 1736 [(set (reg:CCFP CC_REGNUM) 1737 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t") 1738 (match_operand:SF 1 "vfp_compare_operand" "tG")))] 1739 "TARGET_32BIT && TARGET_HARD_FLOAT" 1740 "#" 1741 "TARGET_32BIT && TARGET_HARD_FLOAT" 1742 [(set (reg:CCFP VFPCC_REGNUM) 1743 (compare:CCFP (match_dup 0) 1744 (match_dup 1))) 1745 (set (reg:CCFP CC_REGNUM) 1746 (reg:CCFP VFPCC_REGNUM))] 1747 "" 1748) 1749 1750(define_insn_and_split "*cmpsf_trap_split_vfp" 1751 [(set (reg:CCFPE CC_REGNUM) 1752 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t") 1753 (match_operand:SF 1 "vfp_compare_operand" "tG")))] 1754 "TARGET_32BIT && TARGET_HARD_FLOAT" 1755 "#" 1756 "TARGET_32BIT && TARGET_HARD_FLOAT" 1757 [(set (reg:CCFPE VFPCC_REGNUM) 1758 (compare:CCFPE (match_dup 0) 1759 (match_dup 1))) 1760 (set (reg:CCFPE CC_REGNUM) 1761 (reg:CCFPE VFPCC_REGNUM))] 1762 "" 1763) 1764 1765(define_insn_and_split "*cmpdf_split_vfp" 1766 [(set (reg:CCFP CC_REGNUM) 1767 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w") 1768 (match_operand:DF 1 "vfp_compare_operand" "wG")))] 1769 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1770 "#" 1771 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1772 [(set (reg:CCFP VFPCC_REGNUM) 1773 (compare:CCFP (match_dup 0) 1774 (match_dup 1))) 1775 (set (reg:CCFP CC_REGNUM) 1776 (reg:CCFP VFPCC_REGNUM))] 1777 "" 1778) 1779 1780(define_insn_and_split "*cmpdf_trap_split_vfp" 1781 [(set (reg:CCFPE CC_REGNUM) 1782 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w") 1783 (match_operand:DF 1 "vfp_compare_operand" "wG")))] 1784 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1785 "#" 1786 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1787 [(set (reg:CCFPE VFPCC_REGNUM) 1788 (compare:CCFPE (match_dup 0) 1789 (match_dup 1))) 1790 (set (reg:CCFPE CC_REGNUM) 1791 (reg:CCFPE VFPCC_REGNUM))] 1792 "" 1793) 1794 1795 1796;; Comparison patterns 1797 1798;; In the compare with FP zero case the ARM Architecture Reference Manual 1799;; specifies the immediate to be #0.0. However, some buggy assemblers only 1800;; accept #0. We don't want to autodetect broken assemblers, so output #0. 1801(define_insn "*cmpsf_vfp" 1802 [(set (reg:CCFP VFPCC_REGNUM) 1803 (compare:CCFP (match_operand:SF 0 "s_register_operand" "t,t") 1804 (match_operand:SF 1 "vfp_compare_operand" "t,G")))] 1805 "TARGET_32BIT && TARGET_HARD_FLOAT" 1806 "@ 1807 vcmp%?.f32\\t%0, %1 1808 vcmp%?.f32\\t%0, #0" 1809 [(set_attr "predicable" "yes") 1810 (set_attr "type" "fcmps")] 1811) 1812 1813(define_insn "*cmpsf_trap_vfp" 1814 [(set (reg:CCFPE VFPCC_REGNUM) 1815 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "t,t") 1816 (match_operand:SF 1 "vfp_compare_operand" "t,G")))] 1817 "TARGET_32BIT && TARGET_HARD_FLOAT" 1818 "@ 1819 vcmpe%?.f32\\t%0, %1 1820 vcmpe%?.f32\\t%0, #0" 1821 [(set_attr "predicable" "yes") 1822 (set_attr "type" "fcmps")] 1823) 1824 1825(define_insn "*cmpdf_vfp" 1826 [(set (reg:CCFP VFPCC_REGNUM) 1827 (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w") 1828 (match_operand:DF 1 "vfp_compare_operand" "w,G")))] 1829 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1830 "@ 1831 vcmp%?.f64\\t%P0, %P1 1832 vcmp%?.f64\\t%P0, #0" 1833 [(set_attr "predicable" "yes") 1834 (set_attr "type" "fcmpd")] 1835) 1836 1837(define_insn "*cmpdf_trap_vfp" 1838 [(set (reg:CCFPE VFPCC_REGNUM) 1839 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w") 1840 (match_operand:DF 1 "vfp_compare_operand" "w,G")))] 1841 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" 1842 "@ 1843 vcmpe%?.f64\\t%P0, %P1 1844 vcmpe%?.f64\\t%P0, #0" 1845 [(set_attr "predicable" "yes") 1846 (set_attr "type" "fcmpd")] 1847) 1848 1849;; Fixed point to floating point conversions. 1850(define_insn "*combine_vcvt_f32_<FCVTI32typename>" 1851 [(set (match_operand:SF 0 "s_register_operand" "=t") 1852 (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0")) 1853 (match_operand 2 1854 "const_double_vcvt_power_of_two_reciprocal" "Dt")))] 1855 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math" 1856 "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2" 1857 [(set_attr "predicable" "yes") 1858 (set_attr "type" "f_cvti2f")] 1859) 1860 1861;; Not the ideal way of implementing this. Ideally we would be able to split 1862;; this into a move to a DP register and then a vcvt.f64.i32 1863(define_insn "*combine_vcvt_f64_<FCVTI32typename>" 1864 [(set (match_operand:DF 0 "s_register_operand" "=x,x,w") 1865 (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r")) 1866 (match_operand 2 1867 "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))] 1868 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math 1869 && !TARGET_VFP_SINGLE" 1870 "@ 1871 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2 1872 vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2 1873 vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2" 1874 [(set_attr "predicable" "yes") 1875 (set_attr "ce_count" "2") 1876 (set_attr "type" "f_cvti2f") 1877 (set_attr "length" "8")] 1878) 1879 1880(define_insn "*combine_vcvtf2i" 1881 [(set (match_operand:SI 0 "s_register_operand" "=t") 1882 (fix:SI (fix:SF (mult:SF (match_operand:SF 1 "s_register_operand" "0") 1883 (match_operand 2 1884 "const_double_vcvt_power_of_two" "Dp")))))] 1885 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math" 1886 "vcvt%?.s32.f32\\t%0, %1, %v2" 1887 [(set_attr "predicable" "yes") 1888 (set_attr "type" "f_cvtf2i")] 1889 ) 1890 1891;; FP16 conversions. 1892(define_insn "neon_vcvth<sup>hf" 1893 [(set (match_operand:HF 0 "s_register_operand" "=w") 1894 (unspec:HF 1895 [(match_operand:SI 1 "s_register_operand" "w")] 1896 VCVTH_US))] 1897 "TARGET_VFP_FP16INST" 1898 "vcvt.f16.<sup>%#32\t%0, %1" 1899 [(set_attr "conds" "unconditional") 1900 (set_attr "type" "f_cvti2f")] 1901) 1902 1903(define_insn "neon_vcvth<sup>si" 1904 [(set (match_operand:SI 0 "s_register_operand" "=w") 1905 (unspec:SI 1906 [(match_operand:HF 1 "s_register_operand" "w")] 1907 VCVTH_US))] 1908 "TARGET_VFP_FP16INST" 1909 "vcvt.<sup>%#32.f16\t%0, %1" 1910 [(set_attr "conds" "unconditional") 1911 (set_attr "type" "f_cvtf2i")] 1912) 1913 1914;; The neon_vcvth<sup>_nhf patterns are used to generate the instruction for the 1915;; vcvth_n_f16_<sup>32 arm_fp16 intrinsics. They are complicated by the 1916;; hardware requirement that the source and destination registers are the same 1917;; despite having different machine modes. The approach is to use a temporary 1918;; register for the conversion and move that to the correct destination. 1919 1920;; Generate an unspec pattern for the intrinsic. 1921(define_insn "neon_vcvth<sup>_nhf_unspec" 1922 [(set 1923 (match_operand:SI 0 "s_register_operand" "=w") 1924 (unspec:SI 1925 [(match_operand:SI 1 "s_register_operand" "0") 1926 (match_operand:SI 2 "immediate_operand" "i")] 1927 VCVT_HF_US_N)) 1928 (set 1929 (match_operand:HF 3 "s_register_operand" "=w") 1930 (float_truncate:HF (float:SF (match_dup 0))))] 1931 "TARGET_VFP_FP16INST" 1932{ 1933 arm_const_bounds (operands[2], 1, 33); 1934 return "vcvt.f16.<sup>32\t%0, %0, %2\;vmov.f32\t%3, %0"; 1935} 1936 [(set_attr "conds" "unconditional") 1937 (set_attr "type" "f_cvti2f")] 1938) 1939 1940;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics. 1941(define_expand "neon_vcvth<sup>_nhf" 1942 [(match_operand:HF 0 "s_register_operand") 1943 (unspec:HF [(match_operand:SI 1 "s_register_operand") 1944 (match_operand:SI 2 "immediate_operand")] 1945 VCVT_HF_US_N)] 1946"TARGET_VFP_FP16INST" 1947{ 1948 rtx op1 = gen_reg_rtx (SImode); 1949 1950 arm_const_bounds (operands[2], 1, 33); 1951 1952 emit_move_insn (op1, operands[1]); 1953 emit_insn (gen_neon_vcvth<sup>_nhf_unspec (op1, op1, operands[2], 1954 operands[0])); 1955 DONE; 1956}) 1957 1958;; The neon_vcvth<sup>_nsi patterns are used to generate the instruction for the 1959;; vcvth_n_<sup>32_f16 arm_fp16 intrinsics. They have the same restrictions and 1960;; are implemented in the same way as the neon_vcvth<sup>_nhf patterns. 1961 1962;; Generate an unspec pattern, constraining the registers. 1963(define_insn "neon_vcvth<sup>_nsi_unspec" 1964 [(set (match_operand:SI 0 "s_register_operand" "=w") 1965 (unspec:SI 1966 [(fix:SI 1967 (fix:SF 1968 (float_extend:SF 1969 (match_operand:HF 1 "s_register_operand" "w")))) 1970 (match_operand:SI 2 "immediate_operand" "i")] 1971 VCVT_SI_US_N))] 1972 "TARGET_VFP_FP16INST" 1973{ 1974 arm_const_bounds (operands[2], 1, 33); 1975 return "vmov.f32\t%0, %1\;vcvt.<sup>%#32.f16\t%0, %0, %2"; 1976} 1977 [(set_attr "conds" "unconditional") 1978 (set_attr "type" "f_cvtf2i")] 1979) 1980 1981;; Generate the instruction patterns needed for vcvth_n_f16_s32 neon intrinsics. 1982(define_expand "neon_vcvth<sup>_nsi" 1983 [(match_operand:SI 0 "s_register_operand") 1984 (unspec:SI 1985 [(match_operand:HF 1 "s_register_operand") 1986 (match_operand:SI 2 "immediate_operand")] 1987 VCVT_SI_US_N)] 1988 "TARGET_VFP_FP16INST" 1989{ 1990 rtx op1 = gen_reg_rtx (SImode); 1991 1992 arm_const_bounds (operands[2], 1, 33); 1993 emit_insn (gen_neon_vcvth<sup>_nsi_unspec (op1, operands[1], operands[2])); 1994 emit_move_insn (operands[0], op1); 1995 DONE; 1996}) 1997 1998(define_insn "neon_vcvt<vcvth_op>h<sup>si" 1999 [(set 2000 (match_operand:SI 0 "s_register_operand" "=w") 2001 (unspec:SI 2002 [(match_operand:HF 1 "s_register_operand" "w")] 2003 VCVT_HF_US))] 2004 "TARGET_VFP_FP16INST" 2005 "vcvt<vcvth_op>.<sup>%#32.f16\t%0, %1" 2006 [(set_attr "conds" "unconditional") 2007 (set_attr "type" "f_cvtf2i")] 2008) 2009 2010;; Store multiple insn used in function prologue. 2011(define_insn "*push_multi_vfp" 2012 [(match_parallel 2 "multi_register_push" 2013 [(set (match_operand:BLK 0 "memory_operand" "=m") 2014 (unspec:BLK [(match_operand:DF 1 "vfp_register_operand" "")] 2015 UNSPEC_PUSH_MULT))])] 2016 "TARGET_32BIT && TARGET_VFP_BASE" 2017 "* return vfp_output_vstmd (operands);" 2018 [(set_attr "type" "f_stored")] 2019) 2020 2021;; VRINT round to integral instructions. 2022;; Invoked for the patterns: btruncsf2, btruncdf2, ceilsf2, ceildf2, 2023;; roundsf2, rounddf2, floorsf2, floordf2, nearbyintsf2, nearbyintdf2, 2024;; rintsf2, rintdf2. 2025(define_insn "<vrint_pattern><SDF:mode>2" 2026 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") 2027 (unspec:SDF [(match_operand:SDF 1 2028 "register_operand" "<F_constraint>")] 2029 VRINT))] 2030 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>" 2031 "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1" 2032 [(set_attr "predicable" "<vrint_predicable>") 2033 (set_attr "type" "f_rint<vfp_type>") 2034 (set_attr "conds" "<vrint_conds>")] 2035) 2036 2037;; Implements the lround, lfloor and lceil optabs. 2038(define_insn "l<vrint_pattern><su_optab><mode>si2" 2039 [(set (match_operand:SI 0 "register_operand" "=t") 2040 (FIXUORS:SI (unspec:SDF 2041 [(match_operand:SDF 1 2042 "register_operand" "<F_constraint>")] VCVT)))] 2043 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>" 2044 "vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1" 2045 [(set_attr "conds" "unconditional") 2046 (set_attr "type" "f_cvtf2i")] 2047) 2048 2049;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL. 2050;; The 'smax' and 'smin' RTL standard pattern names do not specify which 2051;; operand will be returned when both operands are zero (i.e. they may not 2052;; honour signed zeroes), or when either operand is NaN. Therefore GCC 2053;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring 2054;; NaNs. 2055 2056(define_insn "smax<mode>3" 2057 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") 2058 (smax:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") 2059 (match_operand:SDF 2 "register_operand" "<F_constraint>")))] 2060 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>" 2061 "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2062 [(set_attr "type" "f_minmax<vfp_type>") 2063 (set_attr "conds" "unconditional")] 2064) 2065 2066(define_insn "smin<mode>3" 2067 [(set (match_operand:SDF 0 "register_operand" "=<F_constraint>") 2068 (smin:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") 2069 (match_operand:SDF 2 "register_operand" "<F_constraint>")))] 2070 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>" 2071 "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2072 [(set_attr "type" "f_minmax<vfp_type>") 2073 (set_attr "conds" "unconditional")] 2074) 2075 2076;; Scalar forms for the IEEE-754 fmax()/fmin() functions 2077 2078(define_insn "neon_<fmaxmin_op>hf" 2079 [(set 2080 (match_operand:HF 0 "s_register_operand" "=w") 2081 (unspec:HF 2082 [(match_operand:HF 1 "s_register_operand" "w") 2083 (match_operand:HF 2 "s_register_operand" "w")] 2084 VMAXMINFNM))] 2085 "TARGET_VFP_FP16INST" 2086 "<fmaxmin_op>.f16\t%0, %1, %2" 2087 [(set_attr "conds" "unconditional") 2088 (set_attr "type" "f_minmaxs")] 2089) 2090 2091(define_insn "<fmaxmin><mode>3" 2092 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>") 2093 (unspec:SDF [(match_operand:SDF 1 "s_register_operand" "<F_constraint>") 2094 (match_operand:SDF 2 "s_register_operand" "<F_constraint>")] 2095 VMAXMINFNM))] 2096 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>" 2097 "<fmaxmin_op>.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2098 [(set_attr "type" "f_minmax<vfp_type>") 2099 (set_attr "conds" "unconditional")] 2100) 2101 2102;; Write Floating-point Status and Control Register. 2103(define_insn "set_fpscr" 2104 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 2105 VUNSPEC_SET_FPSCR)] 2106 "TARGET_VFP_BASE" 2107 "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR" 2108 [(set_attr "type" "mrs")]) 2109 2110;; Read Floating-point Status and Control Register. 2111(define_insn "get_fpscr" 2112 [(set (match_operand:SI 0 "register_operand" "=r") 2113 (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))] 2114 "TARGET_VFP_BASE" 2115 "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR" 2116 [(set_attr "type" "mrs")]) 2117 2118 2119;; Unimplemented insns: 2120;; fldm* 2121;; fstm* 2122;; fmdhr et al (VFPv1) 2123;; Support for xD (single precision only) variants. 2124;; fmrrs, fmsrr 2125 2126;; Load a DF immediate via GPR (where combinations of MOV and MOVT can be used) 2127;; and then move it into a VFP register. 2128(define_insn_and_split "no_literal_pool_df_immediate" 2129 [(set (match_operand:DF 0 "s_register_operand" "=w") 2130 (match_operand:DF 1 "const_double_operand" "F")) 2131 (clobber (match_operand:DF 2 "s_register_operand" "=r"))] 2132 "arm_disable_literal_pool 2133 && TARGET_VFP_BASE 2134 && !arm_const_double_rtx (operands[1]) 2135 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1]))" 2136 "#" 2137 "" 2138 [(const_int 0)] 2139{ 2140 long buf[2]; 2141 int order = BYTES_BIG_ENDIAN ? 1 : 0; 2142 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode); 2143 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32); 2144 ival |= (zext_hwi (buf[1 - order], 32) << 32); 2145 rtx cst = gen_int_mode (ival, DImode); 2146 emit_move_insn (simplify_gen_subreg (DImode, operands[2], DFmode, 0), cst); 2147 emit_move_insn (operands[0], operands[2]); 2148 DONE; 2149} 2150) 2151 2152;; Load a SF immediate via GPR (where combinations of MOV and MOVT can be used) 2153;; and then move it into a VFP register. 2154(define_insn_and_split "no_literal_pool_sf_immediate" 2155 [(set (match_operand:SF 0 "s_register_operand" "=t") 2156 (match_operand:SF 1 "const_double_operand" "E")) 2157 (clobber (match_operand:SF 2 "s_register_operand" "=r"))] 2158 "arm_disable_literal_pool 2159 && TARGET_VFP_BASE 2160 && !vfp3_const_double_rtx (operands[1])" 2161 "#" 2162 "" 2163 [(const_int 0)] 2164{ 2165 long buf; 2166 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode); 2167 rtx cst = gen_int_mode (buf, SImode); 2168 emit_move_insn (simplify_gen_subreg (SImode, operands[2], SFmode, 0), cst); 2169 emit_move_insn (operands[0], operands[2]); 2170 DONE; 2171} 2172) 2173 2174;; CDE instructions using FPU/MVE S/D registers 2175 2176(define_insn "arm_vcx1<mode>" 2177 [(set (match_operand:SIDI 0 "register_operand" "=t") 2178 (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") 2179 (match_operand:SI 2 "const_int_vcde1_operand" "i")] 2180 UNSPEC_VCDE))] 2181 "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" 2182 "vcx1\\tp%c1, %<V_reg>0, #%c2" 2183 [(set_attr "type" "coproc")] 2184) 2185 2186(define_insn "arm_vcx1a<mode>" 2187 [(set (match_operand:SIDI 0 "register_operand" "=t") 2188 (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") 2189 (match_operand:SIDI 2 "register_operand" "0") 2190 (match_operand:SI 3 "const_int_vcde1_operand" "i")] 2191 UNSPEC_VCDEA))] 2192 "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" 2193 "vcx1a\\tp%c1, %<V_reg>0, #%c3" 2194 [(set_attr "type" "coproc")] 2195) 2196 2197(define_insn "arm_vcx2<mode>" 2198 [(set (match_operand:SIDI 0 "register_operand" "=t") 2199 (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") 2200 (match_operand:SIDI 2 "register_operand" "t") 2201 (match_operand:SI 3 "const_int_vcde2_operand" "i")] 2202 UNSPEC_VCDE))] 2203 "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" 2204 "vcx2\\tp%c1, %<V_reg>0, %<V_reg>2, #%c3" 2205 [(set_attr "type" "coproc")] 2206) 2207 2208(define_insn "arm_vcx2a<mode>" 2209 [(set (match_operand:SIDI 0 "register_operand" "=t") 2210 (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") 2211 (match_operand:SIDI 2 "register_operand" "0") 2212 (match_operand:SIDI 3 "register_operand" "t") 2213 (match_operand:SI 4 "const_int_vcde2_operand" "i")] 2214 UNSPEC_VCDEA))] 2215 "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" 2216 "vcx2a\\tp%c1, %<V_reg>0, %<V_reg>3, #%c4" 2217 [(set_attr "type" "coproc")] 2218) 2219 2220(define_insn "arm_vcx3<mode>" 2221 [(set (match_operand:SIDI 0 "register_operand" "=t") 2222 (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") 2223 (match_operand:SIDI 2 "register_operand" "t") 2224 (match_operand:SIDI 3 "register_operand" "t") 2225 (match_operand:SI 4 "const_int_vcde3_operand" "i")] 2226 UNSPEC_VCDE))] 2227 "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" 2228 "vcx3\\tp%c1, %<V_reg>0, %<V_reg>2, %<V_reg>3, #%c4" 2229 [(set_attr "type" "coproc")] 2230) 2231 2232(define_insn "arm_vcx3a<mode>" 2233 [(set (match_operand:SIDI 0 "register_operand" "=t") 2234 (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") 2235 (match_operand:SIDI 2 "register_operand" "0") 2236 (match_operand:SIDI 3 "register_operand" "t") 2237 (match_operand:SIDI 4 "register_operand" "t") 2238 (match_operand:SI 5 "const_int_vcde3_operand" "i")] 2239 UNSPEC_VCDEA))] 2240 "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" 2241 "vcx3a\\tp%c1, %<V_reg>0, %<V_reg>3, %<V_reg>4, #%c5" 2242 [(set_attr "type" "coproc")] 2243) 2244