1;; MIPS Paired-Single Floating and MIPS-3D Instructions. 2;; Copyright (C) 2004-2020 Free Software Foundation, Inc. 3;; 4;; This file is part of GCC. 5;; 6;; GCC is free software; you can redistribute it and/or modify 7;; it under the terms of the GNU General Public License as published by 8;; the Free Software Foundation; either version 3, or (at your option) 9;; any later version. 10;; 11;; GCC is distributed in the hope that it will be useful, 12;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14;; GNU General Public License for more details. 15;; 16;; You should have received a copy of the GNU General Public License 17;; along with GCC; see the file COPYING3. If not see 18;; <http://www.gnu.org/licenses/>. 19 20(define_c_enum "unspec" [ 21 UNSPEC_MOVE_TF_PS 22 UNSPEC_C 23 24 ;; MIPS64/MIPS32R2 alnv.ps 25 UNSPEC_ALNV_PS 26 27 ;; MIPS-3D instructions 28 UNSPEC_CABS 29 30 UNSPEC_ADDR_PS 31 UNSPEC_CVT_PW_PS 32 UNSPEC_CVT_PS_PW 33 UNSPEC_MULR_PS 34 UNSPEC_ABS_PS 35 36 UNSPEC_RSQRT1 37 UNSPEC_RSQRT2 38 UNSPEC_RECIP1 39 UNSPEC_RECIP2 40 UNSPEC_SINGLE_CC 41 UNSPEC_SCC 42]) 43 44(define_insn "*movcc_v2sf_<mode>" 45 [(set (match_operand:V2SF 0 "register_operand" "=f,f") 46 (if_then_else:V2SF 47 (match_operator:GPR 4 "equality_operator" 48 [(match_operand:GPR 1 "register_operand" "d,d") 49 (const_int 0)]) 50 (match_operand:V2SF 2 "register_operand" "f,0") 51 (match_operand:V2SF 3 "register_operand" "0,f")))] 52 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 53 "@ 54 mov%T4.ps\t%0,%2,%1 55 mov%t4.ps\t%0,%3,%1" 56 [(set_attr "type" "condmove") 57 (set_attr "mode" "SF")]) 58 59(define_insn "mips_cond_move_tf_ps" 60 [(set (match_operand:V2SF 0 "register_operand" "=f,f") 61 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f,0") 62 (match_operand:V2SF 2 "register_operand" "0,f") 63 (match_operand:CCV2 3 "register_operand" "z,z")] 64 UNSPEC_MOVE_TF_PS))] 65 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 66 "@ 67 movt.ps\t%0,%1,%3 68 movf.ps\t%0,%2,%3" 69 [(set_attr "type" "condmove") 70 (set_attr "mode" "SF")]) 71 72(define_expand "movv2sfcc" 73 [(set (match_dup 4) (match_operand 1 "comparison_operator")) 74 (set (match_operand:V2SF 0 "register_operand") 75 (if_then_else:V2SF (match_dup 5) 76 (match_operand:V2SF 2 "register_operand") 77 (match_operand:V2SF 3 "register_operand")))] 78 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 79{ 80 /* We can only support MOVN.PS and MOVZ.PS. 81 NOTE: MOVT.PS and MOVF.PS have different semantics from MOVN.PS and 82 MOVZ.PS. MOVT.PS and MOVF.PS depend on two CC values and move 83 each item independently. */ 84 85 if (GET_MODE_CLASS (GET_MODE (XEXP (operands[1], 0))) != MODE_INT) 86 FAIL; 87 88 mips_expand_conditional_move (operands); 89 DONE; 90}) 91 92(define_insn "vec_perm_const_ps" 93 [(set (match_operand:V2SF 0 "register_operand" "=f") 94 (vec_select:V2SF 95 (vec_concat:V4SF 96 (match_operand:V2SF 1 "register_operand" "f") 97 (match_operand:V2SF 2 "register_operand" "f")) 98 (parallel [(match_operand:SI 3 "const_0_or_1_operand" "") 99 (match_operand:SI 4 "const_2_or_3_operand" "")])))] 100 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 101{ 102 /* Let <op>L be the lower part of operand <op> and <op>U be the upper part. 103 The P[UL][UL].PS instruction always specifies the upper part of the 104 result first, so the instruction is: 105 106 P<aUL><bUL>.PS %0,<aop>,<bop> 107 108 where 0U == <aop><aUL> and 0L == <bop><bUL>. 109 110 GCC's vector indices are specified in memory order, which means 111 that vector element 0 is the lower part (L) on little-endian targets 112 and the upper part (U) on big-endian targets. vec_concat likewise 113 concatenates in memory order, which means that operand 3 (being 114 0 or 1) selects part of operand 1 and operand 4 (being 2 or 3) 115 selects part of operand 2. 116 117 Let: 118 119 I3 = INTVAL (operands[3]) 120 I4 = INTVAL (operands[4]) - 2 121 122 Taking the two endiannesses in turn: 123 124 Little-endian: 125 126 The semantics of the RTL pattern are: 127 128 { 0L, 0U } = { X[I3], X[I4 + 2] }, where X = { 1L, 1U, 2L, 2U } 129 130 so: 0L = { 1L, 1U }[I3] (= <bop><bUL>) 131 0U = { 2L, 2U }[I4] (= <aop><aUL>) 132 133 <aop> = 2, <aUL> = I4 ? U : L 134 <bop> = 1, <bUL> = I3 ? U : L 135 136 [LL] !I4 && !I3 [UL] I4 && !I3 137 [LU] !I4 && I3 [UU] I4 && I3 138 139 Big-endian: 140 141 The semantics of the RTL pattern are: 142 143 { 0U, 0L } = { X[I3], X[I4 + 2] }, where X = { 1U, 1L, 2U, 2L } 144 145 so: 0U = { 1U, 1L }[I3] (= <aop><aUL>) 146 0L = { 2U, 2L }[I4] (= <bop><bUL>) 147 148 <aop> = 1, <aUL> = I3 ? L : U 149 <bop> = 2, <bUL> = I4 ? L : U 150 151 [UU] !I3 && !I4 [UL] !I3 && I4 152 [LU] I3 && !I4 [LL] I3 && I4. */ 153 154 static const char * const mnemonics[2][4] = { 155 /* LE */ { "pll.ps\t%0,%2,%1", "pul.ps\t%0,%2,%1", 156 "plu.ps\t%0,%2,%1", "puu.ps\t%0,%2,%1" }, 157 /* BE */ { "puu.ps\t%0,%1,%2", "pul.ps\t%0,%1,%2", 158 "plu.ps\t%0,%1,%2", "pll.ps\t%0,%1,%2" }, 159 }; 160 161 unsigned mask = INTVAL (operands[3]) * 2 + (INTVAL (operands[4]) - 2); 162 return mnemonics[BYTES_BIG_ENDIAN][mask]; 163} 164 [(set_attr "type" "fmove") 165 (set_attr "mode" "SF")]) 166 167;; Expanders for builtins. The instruction: 168;; 169;; P[UL][UL].PS <result>, <a>, <b> 170;; 171;; says that the upper part of <result> is taken from half of <a> and 172;; the lower part of <result> is taken from half of <b>. This means 173;; that the P[UL][UL].PS operand order matches memory order on big-endian 174;; targets; <a> is element 0 of the V2SF result while <b> is element 1. 175;; However, the P[UL][UL].PS operand order is the reverse of memory order 176;; on little-endian targets; <a> is element 1 of the V2SF result while 177;; <b> is element 0. The arguments to vec_perm_const_ps are always in 178;; memory order. 179;; 180;; Similarly, "U" corresponds to element 0 on big-endian targets but 181;; to element 1 on little-endian targets. 182 183(define_expand "mips_puu_ps" 184 [(match_operand:V2SF 0 "register_operand" "") 185 (match_operand:V2SF 1 "register_operand" "") 186 (match_operand:V2SF 2 "register_operand" "")] 187 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 188{ 189 if (BYTES_BIG_ENDIAN) 190 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2], 191 const0_rtx, const2_rtx)); 192 else 193 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1], 194 const1_rtx, GEN_INT (3))); 195 DONE; 196}) 197 198(define_expand "mips_pul_ps" 199 [(match_operand:V2SF 0 "register_operand" "") 200 (match_operand:V2SF 1 "register_operand" "") 201 (match_operand:V2SF 2 "register_operand" "")] 202 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 203{ 204 if (BYTES_BIG_ENDIAN) 205 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2], 206 const0_rtx, GEN_INT (3))); 207 else 208 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1], 209 const0_rtx, GEN_INT (3))); 210 DONE; 211}) 212 213(define_expand "mips_plu_ps" 214 [(match_operand:V2SF 0 "register_operand" "") 215 (match_operand:V2SF 1 "register_operand" "") 216 (match_operand:V2SF 2 "register_operand" "")] 217 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 218{ 219 if (BYTES_BIG_ENDIAN) 220 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2], 221 const1_rtx, const2_rtx)); 222 else 223 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1], 224 const1_rtx, const2_rtx)); 225 DONE; 226}) 227 228(define_expand "mips_pll_ps" 229 [(match_operand:V2SF 0 "register_operand" "") 230 (match_operand:V2SF 1 "register_operand" "") 231 (match_operand:V2SF 2 "register_operand" "")] 232 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 233{ 234 if (BYTES_BIG_ENDIAN) 235 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2], 236 const1_rtx, GEN_INT (3))); 237 else 238 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1], 239 const0_rtx, const2_rtx)); 240 DONE; 241}) 242 243; vec_init 244(define_expand "vec_initv2sfsf" 245 [(match_operand:V2SF 0 "register_operand") 246 (match_operand:V2SF 1 "")] 247 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 248{ 249 mips_expand_vector_init (operands[0], operands[1]); 250 DONE; 251}) 252 253(define_insn "vec_concatv2sf" 254 [(set (match_operand:V2SF 0 "register_operand" "=f") 255 (vec_concat:V2SF 256 (match_operand:SF 1 "register_operand" "f") 257 (match_operand:SF 2 "register_operand" "f")))] 258 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 259{ 260 if (BYTES_BIG_ENDIAN) 261 return "cvt.ps.s\t%0,%1,%2"; 262 else 263 return "cvt.ps.s\t%0,%2,%1"; 264} 265 [(set_attr "type" "fcvt") 266 (set_attr "mode" "SF")]) 267 268;; ??? This is only generated if we perform a vector operation that has to be 269;; emulated. There is no other way to get a vector mode bitfield extract 270;; currently. 271 272(define_insn "vec_extractv2sfsf" 273 [(set (match_operand:SF 0 "register_operand" "=f") 274 (vec_select:SF (match_operand:V2SF 1 "register_operand" "f") 275 (parallel 276 [(match_operand 2 "const_0_or_1_operand" "")])))] 277 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 278{ 279 if (INTVAL (operands[2]) == !BYTES_BIG_ENDIAN) 280 return "cvt.s.pu\t%0,%1"; 281 else 282 return "cvt.s.pl\t%0,%1"; 283} 284 [(set_attr "type" "fcvt") 285 (set_attr "mode" "SF")]) 286 287;; ??? This is only generated if we disable the vec_init pattern. There is 288;; no other way to get a vector mode bitfield store currently. 289 290(define_expand "vec_setv2sf" 291 [(set (match_operand:V2SF 0 "register_operand" "") 292 (vec_select:V2SF 293 (vec_concat:V4SF 294 (match_operand:SF 1 "register_operand" "") 295 (match_dup 0)) 296 (parallel [(match_operand 2 "const_0_or_1_operand" "") 297 (match_dup 3)])))] 298 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 299{ 300 /* We don't have an insert instruction, so we duplicate the float, and 301 then use a PUL instruction. */ 302 rtx temp = gen_reg_rtx (V2SFmode); 303 emit_insn (gen_vec_concatv2sf (temp, operands[1], operands[1])); 304 operands[1] = temp; 305 operands[3] = GEN_INT (1 - INTVAL (operands[2]) + 2); 306}) 307 308; cvt.ps.s - Floating Point Convert Pair to Paired Single 309(define_expand "mips_cvt_ps_s" 310 [(match_operand:V2SF 0 "register_operand") 311 (match_operand:SF 1 "register_operand") 312 (match_operand:SF 2 "register_operand")] 313 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 314{ 315 if (BYTES_BIG_ENDIAN) 316 emit_insn (gen_vec_concatv2sf (operands[0], operands[1], operands[2])); 317 else 318 emit_insn (gen_vec_concatv2sf (operands[0], operands[2], operands[1])); 319 DONE; 320}) 321 322; cvt.s.pl - Floating Point Convert Pair Lower to Single Floating Point 323(define_expand "mips_cvt_s_pl" 324 [(set (match_operand:SF 0 "register_operand") 325 (vec_select:SF (match_operand:V2SF 1 "register_operand") 326 (parallel [(match_dup 2)])))] 327 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 328 { operands[2] = GEN_INT (BYTES_BIG_ENDIAN); }) 329 330; cvt.s.pu - Floating Point Convert Pair Upper to Single Floating Point 331(define_expand "mips_cvt_s_pu" 332 [(set (match_operand:SF 0 "register_operand") 333 (vec_select:SF (match_operand:V2SF 1 "register_operand") 334 (parallel [(match_dup 2)])))] 335 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 336 { operands[2] = GEN_INT (!BYTES_BIG_ENDIAN); }) 337 338; alnv.ps - Floating Point Align Variable 339(define_insn "mips_alnv_ps" 340 [(set (match_operand:V2SF 0 "register_operand" "=f") 341 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f") 342 (match_operand:V2SF 2 "register_operand" "f") 343 (match_operand:SI 3 "register_operand" "d")] 344 UNSPEC_ALNV_PS))] 345 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 346 "alnv.ps\t%0,%1,%2,%3" 347 [(set_attr "type" "fmove") 348 (set_attr "mode" "SF")]) 349 350; addr.ps - Floating Point Reduction Add 351(define_insn "mips_addr_ps" 352 [(set (match_operand:V2SF 0 "register_operand" "=f") 353 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f") 354 (match_operand:V2SF 2 "register_operand" "f")] 355 UNSPEC_ADDR_PS))] 356 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 357 "addr.ps\t%0,%1,%2" 358 [(set_attr "type" "fadd") 359 (set_attr "mode" "SF")]) 360 361(define_expand "reduc_plus_scal_v2sf" 362 [(match_operand:SF 0 "register_operand" "=f") 363 (match_operand:V2SF 1 "register_operand" "f")] 364 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 365 { 366 rtx temp = gen_reg_rtx (V2SFmode); 367 emit_insn (gen_mips_addr_ps (temp, operands[1], operands[1])); 368 rtx lane = BYTES_BIG_ENDIAN ? const1_rtx : const0_rtx; 369 emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane)); 370 DONE; 371 }) 372 373; cvt.pw.ps - Floating Point Convert Paired Single to Paired Word 374(define_insn "mips_cvt_pw_ps" 375 [(set (match_operand:V2SF 0 "register_operand" "=f") 376 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")] 377 UNSPEC_CVT_PW_PS))] 378 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 379 "cvt.pw.ps\t%0,%1" 380 [(set_attr "type" "fcvt") 381 (set_attr "mode" "SF")]) 382 383; cvt.ps.pw - Floating Point Convert Paired Word to Paired Single 384(define_insn "mips_cvt_ps_pw" 385 [(set (match_operand:V2SF 0 "register_operand" "=f") 386 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")] 387 UNSPEC_CVT_PS_PW))] 388 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 389 "cvt.ps.pw\t%0,%1" 390 [(set_attr "type" "fcvt") 391 (set_attr "mode" "SF")]) 392 393; mulr.ps - Floating Point Reduction Multiply 394(define_insn "mips_mulr_ps" 395 [(set (match_operand:V2SF 0 "register_operand" "=f") 396 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f") 397 (match_operand:V2SF 2 "register_operand" "f")] 398 UNSPEC_MULR_PS))] 399 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 400 "mulr.ps\t%0,%1,%2" 401 [(set_attr "type" "fmul") 402 (set_attr "mode" "SF")]) 403 404; abs.ps 405(define_expand "mips_abs_ps" 406 [(set (match_operand:V2SF 0 "register_operand") 407 (unspec:V2SF [(match_operand:V2SF 1 "register_operand")] 408 UNSPEC_ABS_PS))] 409 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 410{ 411 /* If we can ignore NaNs, this operation is equivalent to the 412 rtl ABS code. */ 413 if (!HONOR_NANS (V2SFmode)) 414 { 415 emit_insn (gen_absv2sf2 (operands[0], operands[1])); 416 DONE; 417 } 418}) 419 420(define_insn "*mips_abs_ps" 421 [(set (match_operand:V2SF 0 "register_operand" "=f") 422 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")] 423 UNSPEC_ABS_PS))] 424 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 425 "abs.ps\t%0,%1" 426 [(set_attr "type" "fabs") 427 (set_attr "mode" "SF")]) 428 429;---------------------------------------------------------------------------- 430; Floating Point Comparisons for Scalars 431;---------------------------------------------------------------------------- 432 433(define_insn "mips_cabs_cond_<fmt>" 434 [(set (match_operand:CC 0 "register_operand" "=z") 435 (unspec:CC [(match_operand:SCALARF 1 "register_operand" "f") 436 (match_operand:SCALARF 2 "register_operand" "f") 437 (match_operand 3 "const_int_operand" "")] 438 UNSPEC_CABS))] 439 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 440 "cabs.%Y3.<fmt>\t%0,%1,%2" 441 [(set_attr "type" "fcmp") 442 (set_attr "mode" "FPSW")]) 443 444 445;---------------------------------------------------------------------------- 446; Floating Point Comparisons for Four Singles 447;---------------------------------------------------------------------------- 448 449(define_insn_and_split "mips_c_cond_4s" 450 [(set (match_operand:CCV4 0 "register_operand" "=z") 451 (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f") 452 (match_operand:V2SF 2 "register_operand" "f") 453 (match_operand:V2SF 3 "register_operand" "f") 454 (match_operand:V2SF 4 "register_operand" "f") 455 (match_operand 5 "const_int_operand" "")] 456 UNSPEC_C))] 457 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 458 "#" 459 "&& reload_completed" 460 [(set (match_dup 6) 461 (unspec:CCV2 [(match_dup 1) 462 (match_dup 2) 463 (match_dup 5)] 464 UNSPEC_C)) 465 (set (match_dup 7) 466 (unspec:CCV2 [(match_dup 3) 467 (match_dup 4) 468 (match_dup 5)] 469 UNSPEC_C))] 470{ 471 operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0); 472 operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8); 473} 474 [(set_attr "type" "fcmp") 475 (set_attr "insn_count" "2") 476 (set_attr "mode" "FPSW")]) 477 478(define_insn_and_split "mips_cabs_cond_4s" 479 [(set (match_operand:CCV4 0 "register_operand" "=z") 480 (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f") 481 (match_operand:V2SF 2 "register_operand" "f") 482 (match_operand:V2SF 3 "register_operand" "f") 483 (match_operand:V2SF 4 "register_operand" "f") 484 (match_operand 5 "const_int_operand" "")] 485 UNSPEC_CABS))] 486 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 487 "#" 488 "&& reload_completed" 489 [(set (match_dup 6) 490 (unspec:CCV2 [(match_dup 1) 491 (match_dup 2) 492 (match_dup 5)] 493 UNSPEC_CABS)) 494 (set (match_dup 7) 495 (unspec:CCV2 [(match_dup 3) 496 (match_dup 4) 497 (match_dup 5)] 498 UNSPEC_CABS))] 499{ 500 operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0); 501 operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8); 502} 503 [(set_attr "type" "fcmp") 504 (set_attr "insn_count" "2") 505 (set_attr "mode" "FPSW")]) 506 507 508;---------------------------------------------------------------------------- 509; Floating Point Comparisons for Paired Singles 510;---------------------------------------------------------------------------- 511 512(define_insn "mips_c_cond_ps" 513 [(set (match_operand:CCV2 0 "register_operand" "=z") 514 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f") 515 (match_operand:V2SF 2 "register_operand" "f") 516 (match_operand 3 "const_int_operand" "")] 517 UNSPEC_C))] 518 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 519 "c.%Y3.ps\t%0,%1,%2" 520 [(set_attr "type" "fcmp") 521 (set_attr "mode" "FPSW")]) 522 523(define_insn "mips_cabs_cond_ps" 524 [(set (match_operand:CCV2 0 "register_operand" "=z") 525 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f") 526 (match_operand:V2SF 2 "register_operand" "f") 527 (match_operand 3 "const_int_operand" "")] 528 UNSPEC_CABS))] 529 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 530 "cabs.%Y3.ps\t%0,%1,%2" 531 [(set_attr "type" "fcmp") 532 (set_attr "mode" "FPSW")]) 533 534;; An expander for generating an scc operation. 535(define_expand "scc_ps" 536 [(set (match_operand:CCV2 0) 537 (unspec:CCV2 [(match_operand 1)] UNSPEC_SCC))]) 538 539(define_insn "s<code>_ps" 540 [(set (match_operand:CCV2 0 "register_operand" "=z") 541 (unspec:CCV2 542 [(fcond (match_operand:V2SF 1 "register_operand" "f") 543 (match_operand:V2SF 2 "register_operand" "f"))] 544 UNSPEC_SCC))] 545 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 546 "c.<fcond>.ps\t%0,%1,%2" 547 [(set_attr "type" "fcmp") 548 (set_attr "mode" "FPSW")]) 549 550(define_insn "s<code>_ps" 551 [(set (match_operand:CCV2 0 "register_operand" "=z") 552 (unspec:CCV2 553 [(swapped_fcond (match_operand:V2SF 1 "register_operand" "f") 554 (match_operand:V2SF 2 "register_operand" "f"))] 555 UNSPEC_SCC))] 556 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 557 "c.<swapped_fcond>.ps\t%0,%2,%1" 558 [(set_attr "type" "fcmp") 559 (set_attr "mode" "FPSW")]) 560 561;---------------------------------------------------------------------------- 562; Floating Point Branch Instructions. 563;---------------------------------------------------------------------------- 564 565; Branch on Any of Four Floating Point Condition Codes True 566(define_insn "bc1any4t" 567 [(set (pc) 568 (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z") 569 (const_int 0)) 570 (label_ref (match_operand 0 "" "")) 571 (pc)))] 572 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 573 "%*bc1any4t\t%1,%0%/" 574 [(set_attr "type" "branch")]) 575 576; Branch on Any of Four Floating Point Condition Codes False 577(define_insn "bc1any4f" 578 [(set (pc) 579 (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z") 580 (const_int -1)) 581 (label_ref (match_operand 0 "" "")) 582 (pc)))] 583 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 584 "%*bc1any4f\t%1,%0%/" 585 [(set_attr "type" "branch")]) 586 587; Branch on Any of Two Floating Point Condition Codes True 588(define_insn "bc1any2t" 589 [(set (pc) 590 (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z") 591 (const_int 0)) 592 (label_ref (match_operand 0 "" "")) 593 (pc)))] 594 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 595 "%*bc1any2t\t%1,%0%/" 596 [(set_attr "type" "branch")]) 597 598; Branch on Any of Two Floating Point Condition Codes False 599(define_insn "bc1any2f" 600 [(set (pc) 601 (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z") 602 (const_int -1)) 603 (label_ref (match_operand 0 "" "")) 604 (pc)))] 605 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 606 "%*bc1any2f\t%1,%0%/" 607 [(set_attr "type" "branch")]) 608 609; Used to access one register in a CCV2 pair. Operand 0 is the register 610; pair and operand 1 is the index of the register we want (a CONST_INT). 611(define_expand "single_cc" 612 [(ne (unspec:CC [(match_operand 0) (match_operand 1)] UNSPEC_SINGLE_CC) 613 (const_int 0))]) 614 615; This is a normal floating-point branch pattern, but rather than check 616; a single CCmode register, it checks one register in a CCV2 pair. 617; Operand 2 is the register pair and operand 3 is the index of the 618; register we want. 619(define_insn "*branch_upper_lower" 620 [(set (pc) 621 (if_then_else 622 (match_operator 1 "equality_operator" 623 [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z") 624 (match_operand 3 "const_int_operand")] 625 UNSPEC_SINGLE_CC) 626 (const_int 0)]) 627 (label_ref (match_operand 0 "" "")) 628 (pc)))] 629 "TARGET_HARD_FLOAT" 630{ 631 operands[2] 632 = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3])); 633 return mips_output_conditional_branch (insn, operands, 634 MIPS_BRANCH ("b%F1", "%2,%0"), 635 MIPS_BRANCH ("b%W1", "%2,%0")); 636} 637 [(set_attr "type" "branch")]) 638 639; As above, but with the sense of the condition reversed. 640(define_insn "*branch_upper_lower_inverted" 641 [(set (pc) 642 (if_then_else 643 (match_operator 1 "equality_operator" 644 [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z") 645 (match_operand 3 "const_int_operand")] 646 UNSPEC_SINGLE_CC) 647 (const_int 0)]) 648 (pc) 649 (label_ref (match_operand 0 "" ""))))] 650 "TARGET_HARD_FLOAT" 651{ 652 operands[2] 653 = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3])); 654 return mips_output_conditional_branch (insn, operands, 655 MIPS_BRANCH ("b%W1", "%2,%0"), 656 MIPS_BRANCH ("b%F1", "%2,%0")); 657} 658 [(set_attr "type" "branch")]) 659 660;---------------------------------------------------------------------------- 661; Floating Point Reduced Precision Reciprocal Square Root Instructions. 662;---------------------------------------------------------------------------- 663 664(define_insn "mips_rsqrt1_<fmt>" 665 [(set (match_operand:ANYF 0 "register_operand" "=f") 666 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")] 667 UNSPEC_RSQRT1))] 668 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 669 "rsqrt1.<fmt>\t%0,%1" 670 [(set_attr "type" "frsqrt1") 671 (set_attr "mode" "<UNITMODE>")]) 672 673(define_insn "mips_rsqrt2_<fmt>" 674 [(set (match_operand:ANYF 0 "register_operand" "=f") 675 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f") 676 (match_operand:ANYF 2 "register_operand" "f")] 677 UNSPEC_RSQRT2))] 678 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 679 "rsqrt2.<fmt>\t%0,%1,%2" 680 [(set_attr "type" "frsqrt2") 681 (set_attr "mode" "<UNITMODE>")]) 682 683(define_insn "mips_recip1_<fmt>" 684 [(set (match_operand:ANYF 0 "register_operand" "=f") 685 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")] 686 UNSPEC_RECIP1))] 687 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 688 "recip1.<fmt>\t%0,%1" 689 [(set_attr "type" "frdiv1") 690 (set_attr "mode" "<UNITMODE>")]) 691 692(define_insn "mips_recip2_<fmt>" 693 [(set (match_operand:ANYF 0 "register_operand" "=f") 694 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f") 695 (match_operand:ANYF 2 "register_operand" "f")] 696 UNSPEC_RECIP2))] 697 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 698 "recip2.<fmt>\t%0,%1,%2" 699 [(set_attr "type" "frdiv2") 700 (set_attr "mode" "<UNITMODE>")]) 701 702(define_expand "vcondv2sfv2sf" 703 [(set (match_operand:V2SF 0 "register_operand") 704 (if_then_else:V2SF 705 (match_operator 3 "" 706 [(match_operand:V2SF 4 "register_operand") 707 (match_operand:V2SF 5 "register_operand")]) 708 (match_operand:V2SF 1 "register_operand") 709 (match_operand:V2SF 2 "register_operand")))] 710 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 711{ 712 mips_expand_vcondv2sf (operands[0], operands[1], operands[2], 713 GET_CODE (operands[3]), operands[4], operands[5]); 714 DONE; 715}) 716 717(define_expand "sminv2sf3" 718 [(set (match_operand:V2SF 0 "register_operand") 719 (smin:V2SF (match_operand:V2SF 1 "register_operand") 720 (match_operand:V2SF 2 "register_operand")))] 721 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 722{ 723 mips_expand_vcondv2sf (operands[0], operands[1], operands[2], 724 LE, operands[1], operands[2]); 725 DONE; 726}) 727 728(define_expand "smaxv2sf3" 729 [(set (match_operand:V2SF 0 "register_operand") 730 (smax:V2SF (match_operand:V2SF 1 "register_operand") 731 (match_operand:V2SF 2 "register_operand")))] 732 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 733{ 734 mips_expand_vcondv2sf (operands[0], operands[1], operands[2], 735 LE, operands[2], operands[1]); 736 DONE; 737}) 738 739(define_expand "reduc_smin_scal_v2sf" 740 [(match_operand:SF 0 "register_operand") 741 (match_operand:V2SF 1 "register_operand")] 742 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 743{ 744 rtx temp = gen_reg_rtx (V2SFmode); 745 mips_expand_vec_reduc (temp, operands[1], gen_sminv2sf3); 746 rtx lane = BYTES_BIG_ENDIAN ? const1_rtx : const0_rtx; 747 emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane)); 748 DONE; 749}) 750 751(define_expand "reduc_smax_scal_v2sf" 752 [(match_operand:SF 0 "register_operand") 753 (match_operand:V2SF 1 "register_operand")] 754 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 755{ 756 rtx temp = gen_reg_rtx (V2SFmode); 757 mips_expand_vec_reduc (temp, operands[1], gen_smaxv2sf3); 758 rtx lane = BYTES_BIG_ENDIAN ? const1_rtx : const0_rtx; 759 emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane)); 760 DONE; 761}) 762