1;; MIPS Paired-Single Floating and MIPS-3D Instructions. 2;; Copyright (C) 2004-2015 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(define_expand "vec_perm_constv2sf" 168 [(match_operand:V2SF 0 "register_operand" "") 169 (match_operand:V2SF 1 "register_operand" "") 170 (match_operand:V2SF 2 "register_operand" "") 171 (match_operand:V2SI 3 "" "")] 172 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 173{ 174 if (mips_expand_vec_perm_const (operands)) 175 DONE; 176 else 177 FAIL; 178}) 179 180;; Expanders for builtins. The instruction: 181;; 182;; P[UL][UL].PS <result>, <a>, <b> 183;; 184;; says that the upper part of <result> is taken from half of <a> and 185;; the lower part of <result> is taken from half of <b>. This means 186;; that the P[UL][UL].PS operand order matches memory order on big-endian 187;; targets; <a> is element 0 of the V2SF result while <b> is element 1. 188;; However, the P[UL][UL].PS operand order is the reverse of memory order 189;; on little-endian targets; <a> is element 1 of the V2SF result while 190;; <b> is element 0. The arguments to vec_perm_const_ps are always in 191;; memory order. 192;; 193;; Similarly, "U" corresponds to element 0 on big-endian targets but 194;; to element 1 on little-endian targets. 195 196(define_expand "mips_puu_ps" 197 [(match_operand:V2SF 0 "register_operand" "") 198 (match_operand:V2SF 1 "register_operand" "") 199 (match_operand:V2SF 2 "register_operand" "")] 200 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 201{ 202 if (BYTES_BIG_ENDIAN) 203 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2], 204 const0_rtx, const2_rtx)); 205 else 206 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1], 207 const1_rtx, GEN_INT (3))); 208 DONE; 209}) 210 211(define_expand "mips_pul_ps" 212 [(match_operand:V2SF 0 "register_operand" "") 213 (match_operand:V2SF 1 "register_operand" "") 214 (match_operand:V2SF 2 "register_operand" "")] 215 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 216{ 217 if (BYTES_BIG_ENDIAN) 218 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2], 219 const0_rtx, GEN_INT (3))); 220 else 221 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1], 222 const0_rtx, GEN_INT (3))); 223 DONE; 224}) 225 226(define_expand "mips_plu_ps" 227 [(match_operand:V2SF 0 "register_operand" "") 228 (match_operand:V2SF 1 "register_operand" "") 229 (match_operand:V2SF 2 "register_operand" "")] 230 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 231{ 232 if (BYTES_BIG_ENDIAN) 233 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2], 234 const1_rtx, const2_rtx)); 235 else 236 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1], 237 const1_rtx, const2_rtx)); 238 DONE; 239}) 240 241(define_expand "mips_pll_ps" 242 [(match_operand:V2SF 0 "register_operand" "") 243 (match_operand:V2SF 1 "register_operand" "") 244 (match_operand:V2SF 2 "register_operand" "")] 245 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 246{ 247 if (BYTES_BIG_ENDIAN) 248 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2], 249 const1_rtx, GEN_INT (3))); 250 else 251 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1], 252 const0_rtx, const2_rtx)); 253 DONE; 254}) 255 256; vec_init 257(define_expand "vec_initv2sf" 258 [(match_operand:V2SF 0 "register_operand") 259 (match_operand:V2SF 1 "")] 260 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 261{ 262 mips_expand_vector_init (operands[0], operands[1]); 263 DONE; 264}) 265 266(define_insn "vec_concatv2sf" 267 [(set (match_operand:V2SF 0 "register_operand" "=f") 268 (vec_concat:V2SF 269 (match_operand:SF 1 "register_operand" "f") 270 (match_operand:SF 2 "register_operand" "f")))] 271 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 272{ 273 if (BYTES_BIG_ENDIAN) 274 return "cvt.ps.s\t%0,%1,%2"; 275 else 276 return "cvt.ps.s\t%0,%2,%1"; 277} 278 [(set_attr "type" "fcvt") 279 (set_attr "mode" "SF")]) 280 281;; ??? This is only generated if we perform a vector operation that has to be 282;; emulated. There is no other way to get a vector mode bitfield extract 283;; currently. 284 285(define_insn "vec_extractv2sf" 286 [(set (match_operand:SF 0 "register_operand" "=f") 287 (vec_select:SF (match_operand:V2SF 1 "register_operand" "f") 288 (parallel 289 [(match_operand 2 "const_0_or_1_operand" "")])))] 290 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 291{ 292 if (INTVAL (operands[2]) == !BYTES_BIG_ENDIAN) 293 return "cvt.s.pu\t%0,%1"; 294 else 295 return "cvt.s.pl\t%0,%1"; 296} 297 [(set_attr "type" "fcvt") 298 (set_attr "mode" "SF")]) 299 300;; ??? This is only generated if we disable the vec_init pattern. There is 301;; no other way to get a vector mode bitfield store currently. 302 303(define_expand "vec_setv2sf" 304 [(set (match_operand:V2SF 0 "register_operand" "") 305 (vec_select:V2SF 306 (vec_concat:V4SF 307 (match_operand:SF 1 "register_operand" "") 308 (match_dup 0)) 309 (parallel [(match_operand 2 "const_0_or_1_operand" "") 310 (match_dup 3)])))] 311 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 312{ 313 /* We don't have an insert instruction, so we duplicate the float, and 314 then use a PUL instruction. */ 315 rtx temp = gen_reg_rtx (V2SFmode); 316 emit_insn (gen_vec_concatv2sf (temp, operands[1], operands[1])); 317 operands[1] = temp; 318 operands[3] = GEN_INT (1 - INTVAL (operands[2]) + 2); 319}) 320 321; cvt.ps.s - Floating Point Convert Pair to Paired Single 322(define_expand "mips_cvt_ps_s" 323 [(match_operand:V2SF 0 "register_operand") 324 (match_operand:SF 1 "register_operand") 325 (match_operand:SF 2 "register_operand")] 326 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 327{ 328 if (BYTES_BIG_ENDIAN) 329 emit_insn (gen_vec_concatv2sf (operands[0], operands[1], operands[2])); 330 else 331 emit_insn (gen_vec_concatv2sf (operands[0], operands[2], operands[1])); 332 DONE; 333}) 334 335; cvt.s.pl - Floating Point Convert Pair Lower to Single Floating Point 336(define_expand "mips_cvt_s_pl" 337 [(set (match_operand:SF 0 "register_operand") 338 (vec_select:SF (match_operand:V2SF 1 "register_operand") 339 (parallel [(match_dup 2)])))] 340 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 341 { operands[2] = GEN_INT (BYTES_BIG_ENDIAN); }) 342 343; cvt.s.pu - Floating Point Convert Pair Upper to Single Floating Point 344(define_expand "mips_cvt_s_pu" 345 [(set (match_operand:SF 0 "register_operand") 346 (vec_select:SF (match_operand:V2SF 1 "register_operand") 347 (parallel [(match_dup 2)])))] 348 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 349 { operands[2] = GEN_INT (!BYTES_BIG_ENDIAN); }) 350 351; alnv.ps - Floating Point Align Variable 352(define_insn "mips_alnv_ps" 353 [(set (match_operand:V2SF 0 "register_operand" "=f") 354 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f") 355 (match_operand:V2SF 2 "register_operand" "f") 356 (match_operand:SI 3 "register_operand" "d")] 357 UNSPEC_ALNV_PS))] 358 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 359 "alnv.ps\t%0,%1,%2,%3" 360 [(set_attr "type" "fmove") 361 (set_attr "mode" "SF")]) 362 363; addr.ps - Floating Point Reduction Add 364(define_insn "mips_addr_ps" 365 [(set (match_operand:V2SF 0 "register_operand" "=f") 366 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f") 367 (match_operand:V2SF 2 "register_operand" "f")] 368 UNSPEC_ADDR_PS))] 369 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 370 "addr.ps\t%0,%1,%2" 371 [(set_attr "type" "fadd") 372 (set_attr "mode" "SF")]) 373 374(define_insn "reduc_splus_v2sf" 375 [(set (match_operand:V2SF 0 "register_operand" "=f") 376 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f") 377 (match_dup 1)] 378 UNSPEC_ADDR_PS))] 379 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 380 "") 381 382; cvt.pw.ps - Floating Point Convert Paired Single to Paired Word 383(define_insn "mips_cvt_pw_ps" 384 [(set (match_operand:V2SF 0 "register_operand" "=f") 385 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")] 386 UNSPEC_CVT_PW_PS))] 387 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 388 "cvt.pw.ps\t%0,%1" 389 [(set_attr "type" "fcvt") 390 (set_attr "mode" "SF")]) 391 392; cvt.ps.pw - Floating Point Convert Paired Word to Paired Single 393(define_insn "mips_cvt_ps_pw" 394 [(set (match_operand:V2SF 0 "register_operand" "=f") 395 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")] 396 UNSPEC_CVT_PS_PW))] 397 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 398 "cvt.ps.pw\t%0,%1" 399 [(set_attr "type" "fcvt") 400 (set_attr "mode" "SF")]) 401 402; mulr.ps - Floating Point Reduction Multiply 403(define_insn "mips_mulr_ps" 404 [(set (match_operand:V2SF 0 "register_operand" "=f") 405 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f") 406 (match_operand:V2SF 2 "register_operand" "f")] 407 UNSPEC_MULR_PS))] 408 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 409 "mulr.ps\t%0,%1,%2" 410 [(set_attr "type" "fmul") 411 (set_attr "mode" "SF")]) 412 413; abs.ps 414(define_expand "mips_abs_ps" 415 [(set (match_operand:V2SF 0 "register_operand") 416 (unspec:V2SF [(match_operand:V2SF 1 "register_operand")] 417 UNSPEC_ABS_PS))] 418 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 419{ 420 /* If we can ignore NaNs, this operation is equivalent to the 421 rtl ABS code. */ 422 if (!HONOR_NANS (V2SFmode)) 423 { 424 emit_insn (gen_absv2sf2 (operands[0], operands[1])); 425 DONE; 426 } 427}) 428 429(define_insn "*mips_abs_ps" 430 [(set (match_operand:V2SF 0 "register_operand" "=f") 431 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")] 432 UNSPEC_ABS_PS))] 433 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 434 "abs.ps\t%0,%1" 435 [(set_attr "type" "fabs") 436 (set_attr "mode" "SF")]) 437 438;---------------------------------------------------------------------------- 439; Floating Point Comparisons for Scalars 440;---------------------------------------------------------------------------- 441 442(define_insn "mips_cabs_cond_<fmt>" 443 [(set (match_operand:CC 0 "register_operand" "=z") 444 (unspec:CC [(match_operand:SCALARF 1 "register_operand" "f") 445 (match_operand:SCALARF 2 "register_operand" "f") 446 (match_operand 3 "const_int_operand" "")] 447 UNSPEC_CABS))] 448 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 449 "cabs.%Y3.<fmt>\t%0,%1,%2" 450 [(set_attr "type" "fcmp") 451 (set_attr "mode" "FPSW")]) 452 453 454;---------------------------------------------------------------------------- 455; Floating Point Comparisons for Four Singles 456;---------------------------------------------------------------------------- 457 458(define_insn_and_split "mips_c_cond_4s" 459 [(set (match_operand:CCV4 0 "register_operand" "=z") 460 (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f") 461 (match_operand:V2SF 2 "register_operand" "f") 462 (match_operand:V2SF 3 "register_operand" "f") 463 (match_operand:V2SF 4 "register_operand" "f") 464 (match_operand 5 "const_int_operand" "")] 465 UNSPEC_C))] 466 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 467 "#" 468 "&& reload_completed" 469 [(set (match_dup 6) 470 (unspec:CCV2 [(match_dup 1) 471 (match_dup 2) 472 (match_dup 5)] 473 UNSPEC_C)) 474 (set (match_dup 7) 475 (unspec:CCV2 [(match_dup 3) 476 (match_dup 4) 477 (match_dup 5)] 478 UNSPEC_C))] 479{ 480 operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0); 481 operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8); 482} 483 [(set_attr "type" "fcmp") 484 (set_attr "insn_count" "2") 485 (set_attr "mode" "FPSW")]) 486 487(define_insn_and_split "mips_cabs_cond_4s" 488 [(set (match_operand:CCV4 0 "register_operand" "=z") 489 (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f") 490 (match_operand:V2SF 2 "register_operand" "f") 491 (match_operand:V2SF 3 "register_operand" "f") 492 (match_operand:V2SF 4 "register_operand" "f") 493 (match_operand 5 "const_int_operand" "")] 494 UNSPEC_CABS))] 495 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 496 "#" 497 "&& reload_completed" 498 [(set (match_dup 6) 499 (unspec:CCV2 [(match_dup 1) 500 (match_dup 2) 501 (match_dup 5)] 502 UNSPEC_CABS)) 503 (set (match_dup 7) 504 (unspec:CCV2 [(match_dup 3) 505 (match_dup 4) 506 (match_dup 5)] 507 UNSPEC_CABS))] 508{ 509 operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0); 510 operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8); 511} 512 [(set_attr "type" "fcmp") 513 (set_attr "insn_count" "2") 514 (set_attr "mode" "FPSW")]) 515 516 517;---------------------------------------------------------------------------- 518; Floating Point Comparisons for Paired Singles 519;---------------------------------------------------------------------------- 520 521(define_insn "mips_c_cond_ps" 522 [(set (match_operand:CCV2 0 "register_operand" "=z") 523 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f") 524 (match_operand:V2SF 2 "register_operand" "f") 525 (match_operand 3 "const_int_operand" "")] 526 UNSPEC_C))] 527 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 528 "c.%Y3.ps\t%0,%1,%2" 529 [(set_attr "type" "fcmp") 530 (set_attr "mode" "FPSW")]) 531 532(define_insn "mips_cabs_cond_ps" 533 [(set (match_operand:CCV2 0 "register_operand" "=z") 534 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f") 535 (match_operand:V2SF 2 "register_operand" "f") 536 (match_operand 3 "const_int_operand" "")] 537 UNSPEC_CABS))] 538 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 539 "cabs.%Y3.ps\t%0,%1,%2" 540 [(set_attr "type" "fcmp") 541 (set_attr "mode" "FPSW")]) 542 543;; An expander for generating an scc operation. 544(define_expand "scc_ps" 545 [(set (match_operand:CCV2 0) 546 (unspec:CCV2 [(match_operand 1)] UNSPEC_SCC))]) 547 548(define_insn "s<code>_ps" 549 [(set (match_operand:CCV2 0 "register_operand" "=z") 550 (unspec:CCV2 551 [(fcond (match_operand:V2SF 1 "register_operand" "f") 552 (match_operand:V2SF 2 "register_operand" "f"))] 553 UNSPEC_SCC))] 554 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 555 "c.<fcond>.ps\t%0,%1,%2" 556 [(set_attr "type" "fcmp") 557 (set_attr "mode" "FPSW")]) 558 559(define_insn "s<code>_ps" 560 [(set (match_operand:CCV2 0 "register_operand" "=z") 561 (unspec:CCV2 562 [(swapped_fcond (match_operand:V2SF 1 "register_operand" "f") 563 (match_operand:V2SF 2 "register_operand" "f"))] 564 UNSPEC_SCC))] 565 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 566 "c.<swapped_fcond>.ps\t%0,%2,%1" 567 [(set_attr "type" "fcmp") 568 (set_attr "mode" "FPSW")]) 569 570;---------------------------------------------------------------------------- 571; Floating Point Branch Instructions. 572;---------------------------------------------------------------------------- 573 574; Branch on Any of Four Floating Point Condition Codes True 575(define_insn "bc1any4t" 576 [(set (pc) 577 (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z") 578 (const_int 0)) 579 (label_ref (match_operand 0 "" "")) 580 (pc)))] 581 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 582 "%*bc1any4t\t%1,%0%/" 583 [(set_attr "type" "branch")]) 584 585; Branch on Any of Four Floating Point Condition Codes False 586(define_insn "bc1any4f" 587 [(set (pc) 588 (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z") 589 (const_int -1)) 590 (label_ref (match_operand 0 "" "")) 591 (pc)))] 592 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 593 "%*bc1any4f\t%1,%0%/" 594 [(set_attr "type" "branch")]) 595 596; Branch on Any of Two Floating Point Condition Codes True 597(define_insn "bc1any2t" 598 [(set (pc) 599 (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z") 600 (const_int 0)) 601 (label_ref (match_operand 0 "" "")) 602 (pc)))] 603 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 604 "%*bc1any2t\t%1,%0%/" 605 [(set_attr "type" "branch")]) 606 607; Branch on Any of Two Floating Point Condition Codes False 608(define_insn "bc1any2f" 609 [(set (pc) 610 (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z") 611 (const_int -1)) 612 (label_ref (match_operand 0 "" "")) 613 (pc)))] 614 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 615 "%*bc1any2f\t%1,%0%/" 616 [(set_attr "type" "branch")]) 617 618; Used to access one register in a CCV2 pair. Operand 0 is the register 619; pair and operand 1 is the index of the register we want (a CONST_INT). 620(define_expand "single_cc" 621 [(ne (unspec:CC [(match_operand 0) (match_operand 1)] UNSPEC_SINGLE_CC) 622 (const_int 0))]) 623 624; This is a normal floating-point branch pattern, but rather than check 625; a single CCmode register, it checks one register in a CCV2 pair. 626; Operand 2 is the register pair and operand 3 is the index of the 627; register we want. 628(define_insn "*branch_upper_lower" 629 [(set (pc) 630 (if_then_else 631 (match_operator 1 "equality_operator" 632 [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z") 633 (match_operand 3 "const_int_operand")] 634 UNSPEC_SINGLE_CC) 635 (const_int 0)]) 636 (label_ref (match_operand 0 "" "")) 637 (pc)))] 638 "TARGET_HARD_FLOAT" 639{ 640 operands[2] 641 = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3])); 642 return mips_output_conditional_branch (insn, operands, 643 MIPS_BRANCH ("b%F1", "%2,%0"), 644 MIPS_BRANCH ("b%W1", "%2,%0")); 645} 646 [(set_attr "type" "branch")]) 647 648; As above, but with the sense of the condition reversed. 649(define_insn "*branch_upper_lower_inverted" 650 [(set (pc) 651 (if_then_else 652 (match_operator 1 "equality_operator" 653 [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z") 654 (match_operand 3 "const_int_operand")] 655 UNSPEC_SINGLE_CC) 656 (const_int 0)]) 657 (pc) 658 (label_ref (match_operand 0 "" ""))))] 659 "TARGET_HARD_FLOAT" 660{ 661 operands[2] 662 = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3])); 663 return mips_output_conditional_branch (insn, operands, 664 MIPS_BRANCH ("b%W1", "%2,%0"), 665 MIPS_BRANCH ("b%F1", "%2,%0")); 666} 667 [(set_attr "type" "branch")]) 668 669;---------------------------------------------------------------------------- 670; Floating Point Reduced Precision Reciprocal Square Root Instructions. 671;---------------------------------------------------------------------------- 672 673(define_insn "mips_rsqrt1_<fmt>" 674 [(set (match_operand:ANYF 0 "register_operand" "=f") 675 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")] 676 UNSPEC_RSQRT1))] 677 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 678 "rsqrt1.<fmt>\t%0,%1" 679 [(set_attr "type" "frsqrt1") 680 (set_attr "mode" "<UNITMODE>")]) 681 682(define_insn "mips_rsqrt2_<fmt>" 683 [(set (match_operand:ANYF 0 "register_operand" "=f") 684 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f") 685 (match_operand:ANYF 2 "register_operand" "f")] 686 UNSPEC_RSQRT2))] 687 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 688 "rsqrt2.<fmt>\t%0,%1,%2" 689 [(set_attr "type" "frsqrt2") 690 (set_attr "mode" "<UNITMODE>")]) 691 692(define_insn "mips_recip1_<fmt>" 693 [(set (match_operand:ANYF 0 "register_operand" "=f") 694 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")] 695 UNSPEC_RECIP1))] 696 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 697 "recip1.<fmt>\t%0,%1" 698 [(set_attr "type" "frdiv1") 699 (set_attr "mode" "<UNITMODE>")]) 700 701(define_insn "mips_recip2_<fmt>" 702 [(set (match_operand:ANYF 0 "register_operand" "=f") 703 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f") 704 (match_operand:ANYF 2 "register_operand" "f")] 705 UNSPEC_RECIP2))] 706 "TARGET_HARD_FLOAT && TARGET_MIPS3D" 707 "recip2.<fmt>\t%0,%1,%2" 708 [(set_attr "type" "frdiv2") 709 (set_attr "mode" "<UNITMODE>")]) 710 711(define_expand "vcondv2sfv2sf" 712 [(set (match_operand:V2SF 0 "register_operand") 713 (if_then_else:V2SF 714 (match_operator 3 "" 715 [(match_operand:V2SF 4 "register_operand") 716 (match_operand:V2SF 5 "register_operand")]) 717 (match_operand:V2SF 1 "register_operand") 718 (match_operand:V2SF 2 "register_operand")))] 719 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 720{ 721 mips_expand_vcondv2sf (operands[0], operands[1], operands[2], 722 GET_CODE (operands[3]), operands[4], operands[5]); 723 DONE; 724}) 725 726(define_expand "sminv2sf3" 727 [(set (match_operand:V2SF 0 "register_operand") 728 (smin:V2SF (match_operand:V2SF 1 "register_operand") 729 (match_operand:V2SF 2 "register_operand")))] 730 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 731{ 732 mips_expand_vcondv2sf (operands[0], operands[1], operands[2], 733 LE, operands[1], operands[2]); 734 DONE; 735}) 736 737(define_expand "smaxv2sf3" 738 [(set (match_operand:V2SF 0 "register_operand") 739 (smax:V2SF (match_operand:V2SF 1 "register_operand") 740 (match_operand:V2SF 2 "register_operand")))] 741 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 742{ 743 mips_expand_vcondv2sf (operands[0], operands[1], operands[2], 744 LE, operands[2], operands[1]); 745 DONE; 746}) 747 748(define_expand "reduc_smin_v2sf" 749 [(match_operand:V2SF 0 "register_operand") 750 (match_operand:V2SF 1 "register_operand")] 751 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 752{ 753 mips_expand_vec_reduc (operands[0], operands[1], gen_sminv2sf3); 754 DONE; 755}) 756 757(define_expand "reduc_smax_v2sf" 758 [(match_operand:V2SF 0 "register_operand") 759 (match_operand:V2SF 1 "register_operand")] 760 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" 761{ 762 mips_expand_vec_reduc (operands[0], operands[1], gen_smaxv2sf3); 763 DONE; 764}) 765