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