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