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