1;; Machine description for Loongson MultiMedia extensions Instructions (MMI). 2;; Copyright (C) 2008-2020 Free Software Foundation, Inc. 3;; Contributed by CodeSourcery. 4;; 5;; This file is part of GCC. 6;; 7;; GCC is free software; you can redistribute it and/or modify 8;; it 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, 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15;; GNU 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(define_c_enum "unspec" [ 22 UNSPEC_LOONGSON_PAVG 23 UNSPEC_LOONGSON_PCMPEQ 24 UNSPEC_LOONGSON_PCMPGT 25 UNSPEC_LOONGSON_PEXTR 26 UNSPEC_LOONGSON_PINSRH 27 UNSPEC_LOONGSON_VINIT 28 UNSPEC_LOONGSON_PMADD 29 UNSPEC_LOONGSON_PMOVMSK 30 UNSPEC_LOONGSON_PMULHU 31 UNSPEC_LOONGSON_PMULH 32 UNSPEC_LOONGSON_PMULU 33 UNSPEC_LOONGSON_PASUBUB 34 UNSPEC_LOONGSON_BIADD 35 UNSPEC_LOONGSON_PSADBH 36 UNSPEC_LOONGSON_PSHUFH 37 UNSPEC_LOONGSON_PUNPCKH 38 UNSPEC_LOONGSON_PUNPCKL 39 UNSPEC_LOONGSON_PADDD 40 UNSPEC_LOONGSON_PSUBD 41 UNSPEC_LOONGSON_DSLL 42 UNSPEC_LOONGSON_DSRL 43]) 44 45;; Mode iterators and attributes. 46 47;; 64-bit vectors of bytes. 48(define_mode_iterator VB [V8QI]) 49 50;; 64-bit vectors of halfwords. 51(define_mode_iterator VH [V4HI]) 52 53;; 64-bit vectors of words. 54(define_mode_iterator VW [V2SI]) 55 56;; 64-bit vectors of halfwords and bytes. 57(define_mode_iterator VHB [V4HI V8QI]) 58 59;; 64-bit vectors of words and halfwords. 60(define_mode_iterator VWH [V2SI V4HI]) 61 62;; 64-bit vectors of words and bytes 63(define_mode_iterator VWB [V2SI V8QI]) 64 65;; 64-bit vectors of words, halfwords and bytes. 66(define_mode_iterator VWHB [V2SI V4HI V8QI]) 67 68;; 64-bit vectors of words, halfwords and bytes; and DImode. 69(define_mode_iterator VWHBDI [V2SI V4HI V8QI DI]) 70 71;; The Loongson instruction suffixes corresponding to the modes in the 72;; VWHBDI iterator. 73(define_mode_attr V_suffix [(V2SI "w") (V4HI "h") (V8QI "b") (DI "d")]) 74 75;; Given a vector type T, the mode of a vector half the size of T 76;; and with the same number of elements. 77(define_mode_attr V_squash [(V2SI "V2HI") (V4HI "V4QI")]) 78 79;; Given a vector type T, the mode of a vector the same size as T 80;; but with half as many elements. 81(define_mode_attr V_stretch_half [(V2SI "DI") (V4HI "V2SI") (V8QI "V4HI")]) 82 83;; The Loongson instruction suffixes corresponding to the transformation 84;; expressed by V_stretch_half. 85(define_mode_attr V_stretch_half_suffix [(V2SI "wd") (V4HI "hw") (V8QI "bh")]) 86 87;; Given a vector type T, the mode of a vector the same size as T 88;; but with twice as many elements. 89(define_mode_attr V_squash_double [(V2SI "V4HI") (V4HI "V8QI")]) 90 91;; Given a vector type T, the inner mode. 92(define_mode_attr V_inner [(V8QI "QI") (V4HI "HI") (V2SI "SI")]) 93 94;; The Loongson instruction suffixes corresponding to the conversions 95;; specified by V_half_width. 96(define_mode_attr V_squash_double_suffix [(V2SI "wh") (V4HI "hb")]) 97 98;; Move patterns. 99 100;; Expander to legitimize moves involving values of vector modes. 101(define_expand "mov<mode>" 102 [(set (match_operand:VWHB 0) 103 (match_operand:VWHB 1))] 104 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 105{ 106 if (mips_legitimize_move (<MODE>mode, operands[0], operands[1])) 107 DONE; 108}) 109 110;; Handle legitimized moves between values of vector modes. 111(define_insn "mov<mode>_internal" 112 [(set (match_operand:VWHB 0 "nonimmediate_operand" "=m,f,d,f, d, m, d") 113 (match_operand:VWHB 1 "move_operand" "f,m,f,dYG,dYG,dYG,m"))] 114 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 115 { return mips_output_move (operands[0], operands[1]); } 116 [(set_attr "move_type" "fpstore,fpload,mfc,mtc,move,store,load") 117 (set_attr "mode" "DI")]) 118 119;; Initialization of a vector. 120 121(define_expand "vec_init<mode><unitmode>" 122 [(set (match_operand:VWHB 0 "register_operand") 123 (match_operand 1 ""))] 124 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 125{ 126 mips_expand_vector_init (operands[0], operands[1]); 127 DONE; 128}) 129 130;; Helper for vec_init. Initialize element 0 of the output from the input. 131;; All other elements are undefined. 132(define_insn "loongson_vec_init1_<mode>" 133 [(set (match_operand:VHB 0 "register_operand" "=f") 134 (unspec:VHB [(truncate:<V_inner> 135 (match_operand:DI 1 "reg_or_0_operand" "Jd"))] 136 UNSPEC_LOONGSON_VINIT))] 137 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 138 "dmtc1\t%z1,%0" 139 [(set_attr "move_type" "mtc") 140 (set_attr "mode" "DI")]) 141 142;; Helper for vec_initv2si. 143(define_insn "*vec_concatv2si" 144 [(set (match_operand:V2SI 0 "register_operand" "=f") 145 (vec_concat:V2SI 146 (match_operand:SI 1 "register_operand" "f") 147 (match_operand:SI 2 "register_operand" "f")))] 148 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 149 "punpcklwd\t%0,%1,%2" 150 [(set_attr "type" "fcvt")]) 151 152;; Instruction patterns for SIMD instructions. 153 154;; Pack with signed saturation. 155(define_insn "vec_pack_ssat_<mode>" 156 [(set (match_operand:<V_squash_double> 0 "register_operand" "=f") 157 (vec_concat:<V_squash_double> 158 (ss_truncate:<V_squash> 159 (match_operand:VWH 1 "register_operand" "f")) 160 (ss_truncate:<V_squash> 161 (match_operand:VWH 2 "register_operand" "f"))))] 162 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 163 "packss<V_squash_double_suffix>\t%0,%1,%2" 164 [(set_attr "type" "fmul")]) 165 166;; Pack with unsigned saturation. 167(define_insn "vec_pack_usat_<mode>" 168 [(set (match_operand:<V_squash_double> 0 "register_operand" "=f") 169 (vec_concat:<V_squash_double> 170 (us_truncate:<V_squash> 171 (match_operand:VH 1 "register_operand" "f")) 172 (us_truncate:<V_squash> 173 (match_operand:VH 2 "register_operand" "f"))))] 174 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 175 "packus<V_squash_double_suffix>\t%0,%1,%2" 176 [(set_attr "type" "fmul")]) 177 178;; Addition, treating overflow by wraparound. 179(define_insn "add<mode>3" 180 [(set (match_operand:VWHB 0 "register_operand" "=f") 181 (plus:VWHB (match_operand:VWHB 1 "register_operand" "f") 182 (match_operand:VWHB 2 "register_operand" "f")))] 183 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 184 "padd<V_suffix>\t%0,%1,%2" 185 [(set_attr "type" "fadd")]) 186 187;; Addition of doubleword integers stored in FP registers. 188;; Overflow is treated by wraparound. 189;; We use 'unspec' instead of 'plus' here to avoid clash with 190;; mips.md::add<mode>3. If 'plus' was used, then such instruction 191;; would be recognized as adddi3 and reload would make it use 192;; GPRs instead of FPRs. 193(define_insn "loongson_paddd" 194 [(set (match_operand:DI 0 "register_operand" "=f") 195 (unspec:DI [(match_operand:DI 1 "register_operand" "f") 196 (match_operand:DI 2 "register_operand" "f")] 197 UNSPEC_LOONGSON_PADDD))] 198 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 199 "paddd\t%0,%1,%2" 200 [(set_attr "type" "fadd")]) 201 202;; Addition, treating overflow by signed saturation. 203(define_insn "ssadd<mode>3" 204 [(set (match_operand:VHB 0 "register_operand" "=f") 205 (ss_plus:VHB (match_operand:VHB 1 "register_operand" "f") 206 (match_operand:VHB 2 "register_operand" "f")))] 207 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 208 "padds<V_suffix>\t%0,%1,%2" 209 [(set_attr "type" "fadd")]) 210 211;; Addition, treating overflow by unsigned saturation. 212(define_insn "usadd<mode>3" 213 [(set (match_operand:VHB 0 "register_operand" "=f") 214 (us_plus:VHB (match_operand:VHB 1 "register_operand" "f") 215 (match_operand:VHB 2 "register_operand" "f")))] 216 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 217 "paddus<V_suffix>\t%0,%1,%2" 218 [(set_attr "type" "fadd")]) 219 220;; Logical AND NOT. 221(define_insn "loongson_pandn_<V_suffix>" 222 [(set (match_operand:VWHBDI 0 "register_operand" "=f") 223 (and:VWHBDI 224 (not:VWHBDI (match_operand:VWHBDI 1 "register_operand" "f")) 225 (match_operand:VWHBDI 2 "register_operand" "f")))] 226 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 227 "pandn\t%0,%1,%2" 228 [(set_attr "type" "fmul")]) 229 230;; Logical AND. 231(define_insn "and<mode>3" 232 [(set (match_operand:VWHB 0 "register_operand" "=f") 233 (and:VWHB (match_operand:VWHB 1 "register_operand" "f") 234 (match_operand:VWHB 2 "register_operand" "f")))] 235 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 236 "and\t%0,%1,%2" 237 [(set_attr "type" "fmul")]) 238 239;; Logical OR. 240(define_insn "ior<mode>3" 241 [(set (match_operand:VWHB 0 "register_operand" "=f") 242 (ior:VWHB (match_operand:VWHB 1 "register_operand" "f") 243 (match_operand:VWHB 2 "register_operand" "f")))] 244 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 245 "or\t%0,%1,%2" 246 [(set_attr "type" "fcvt")]) 247 248;; Logical XOR. 249(define_insn "xor<mode>3" 250 [(set (match_operand:VWHB 0 "register_operand" "=f") 251 (xor:VWHB (match_operand:VWHB 1 "register_operand" "f") 252 (match_operand:VWHB 2 "register_operand" "f")))] 253 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 254 "xor\t%0,%1,%2" 255 [(set_attr "type" "fmul")]) 256 257;; Logical NOR. 258(define_insn "*loongson_nor" 259 [(set (match_operand:VWHB 0 "register_operand" "=f") 260 (and:VWHB 261 (not:VWHB (match_operand:VWHB 1 "register_operand" "f")) 262 (not:VWHB (match_operand:VWHB 2 "register_operand" "f"))))] 263 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 264 "nor\t%0,%1,%2" 265 [(set_attr "type" "fmul")]) 266 267;; Logical NOT. 268(define_insn "one_cmpl<mode>2" 269 [(set (match_operand:VWHB 0 "register_operand" "=f") 270 (not:VWHB (match_operand:VWHB 1 "register_operand" "f")))] 271 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 272 "nor\t%0,%1,%1" 273 [(set_attr "type" "fmul")]) 274 275;; Average. 276(define_insn "loongson_pavg<V_suffix>" 277 [(set (match_operand:VHB 0 "register_operand" "=f") 278 (unspec:VHB [(match_operand:VHB 1 "register_operand" "f") 279 (match_operand:VHB 2 "register_operand" "f")] 280 UNSPEC_LOONGSON_PAVG))] 281 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 282 "pavg<V_suffix>\t%0,%1,%2" 283 [(set_attr "type" "fadd")]) 284 285;; Equality test. 286(define_insn "loongson_pcmpeq<V_suffix>" 287 [(set (match_operand:VWHB 0 "register_operand" "=f") 288 (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f") 289 (match_operand:VWHB 2 "register_operand" "f")] 290 UNSPEC_LOONGSON_PCMPEQ))] 291 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 292 "pcmpeq<V_suffix>\t%0,%1,%2" 293 [(set_attr "type" "fadd")]) 294 295;; Greater-than test. 296(define_insn "loongson_pcmpgt<V_suffix>" 297 [(set (match_operand:VWHB 0 "register_operand" "=f") 298 (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f") 299 (match_operand:VWHB 2 "register_operand" "f")] 300 UNSPEC_LOONGSON_PCMPGT))] 301 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 302 "pcmpgt<V_suffix>\t%0,%1,%2" 303 [(set_attr "type" "fadd")]) 304 305;; Extract halfword. 306(define_insn "loongson_pextrh" 307 [(set (match_operand:V4HI 0 "register_operand" "=f") 308 (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "f") 309 (match_operand:SI 2 "register_operand" "f")] 310 UNSPEC_LOONGSON_PEXTR))] 311 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 312 "pextrh\t%0,%1,%2" 313 [(set_attr "type" "fcvt")]) 314 315;; Insert halfword. 316(define_insn "loongson_pinsrh_0" 317 [(set (match_operand:V4HI 0 "register_operand" "=f") 318 (vec_select:V4HI 319 (vec_concat:V8HI 320 (match_operand:V4HI 1 "register_operand" "f") 321 (match_operand:V4HI 2 "register_operand" "f")) 322 (parallel [(const_int 4) (const_int 1) 323 (const_int 2) (const_int 3)])))] 324 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 325 "pinsrh_0\t%0,%1,%2" 326 [(set_attr "type" "fdiv")]) 327 328(define_insn "loongson_pinsrh_1" 329 [(set (match_operand:V4HI 0 "register_operand" "=f") 330 (vec_select:V4HI 331 (vec_concat:V8HI 332 (match_operand:V4HI 1 "register_operand" "f") 333 (match_operand:V4HI 2 "register_operand" "f")) 334 (parallel [(const_int 0) (const_int 4) 335 (const_int 2) (const_int 3)])))] 336 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 337 "pinsrh_1\t%0,%1,%2" 338 [(set_attr "type" "fdiv")]) 339 340(define_insn "loongson_pinsrh_2" 341 [(set (match_operand:V4HI 0 "register_operand" "=f") 342 (vec_select:V4HI 343 (vec_concat:V8HI 344 (match_operand:V4HI 1 "register_operand" "f") 345 (match_operand:V4HI 2 "register_operand" "f")) 346 (parallel [(const_int 0) (const_int 1) 347 (const_int 4) (const_int 3)])))] 348 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 349 "pinsrh_2\t%0,%1,%2" 350 [(set_attr "type" "fdiv")]) 351 352(define_insn "loongson_pinsrh_3" 353 [(set (match_operand:V4HI 0 "register_operand" "=f") 354 (vec_select:V4HI 355 (vec_concat:V8HI 356 (match_operand:V4HI 1 "register_operand" "f") 357 (match_operand:V4HI 2 "register_operand" "f")) 358 (parallel [(const_int 0) (const_int 1) 359 (const_int 2) (const_int 4)])))] 360 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 361 "pinsrh_3\t%0,%1,%2" 362 [(set_attr "type" "fdiv")]) 363 364(define_insn "*vec_setv4hi" 365 [(set (match_operand:V4HI 0 "register_operand" "=f") 366 (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "f") 367 (match_operand:SI 2 "register_operand" "f") 368 (match_operand:SI 3 "const_0_to_3_operand" "")] 369 UNSPEC_LOONGSON_PINSRH))] 370 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 371 "pinsrh_%3\t%0,%1,%2" 372 [(set_attr "type" "fdiv")]) 373 374(define_expand "vec_setv4hi" 375 [(set (match_operand:V4HI 0 "register_operand" "=f") 376 (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "f") 377 (match_operand:HI 2 "register_operand" "f") 378 (match_operand:SI 3 "const_0_to_3_operand" "")] 379 UNSPEC_LOONGSON_PINSRH))] 380 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 381{ 382 rtx ext = gen_reg_rtx (SImode); 383 emit_move_insn (ext, gen_lowpart (SImode, operands[2])); 384 operands[2] = ext; 385}) 386 387;; Multiply and add packed integers. 388(define_insn "loongson_pmaddhw" 389 [(set (match_operand:V2SI 0 "register_operand" "=f") 390 (unspec:V2SI [(match_operand:V4HI 1 "register_operand" "f") 391 (match_operand:V4HI 2 "register_operand" "f")] 392 UNSPEC_LOONGSON_PMADD))] 393 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 394 "pmaddhw\t%0,%1,%2" 395 [(set_attr "type" "fmul")]) 396 397(define_expand "sdot_prodv4hi" 398 [(match_operand:V2SI 0 "register_operand" "") 399 (match_operand:V4HI 1 "register_operand" "") 400 (match_operand:V4HI 2 "register_operand" "") 401 (match_operand:V2SI 3 "register_operand" "")] 402 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 403{ 404 rtx t = gen_reg_rtx (V2SImode); 405 emit_insn (gen_loongson_pmaddhw (t, operands[1], operands[2])); 406 emit_insn (gen_addv2si3 (operands[0], t, operands[3])); 407 DONE; 408}) 409 410;; Maximum of signed halfwords. 411(define_insn "smaxv4hi3" 412 [(set (match_operand:V4HI 0 "register_operand" "=f") 413 (smax:V4HI (match_operand:V4HI 1 "register_operand" "f") 414 (match_operand:V4HI 2 "register_operand" "f")))] 415 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 416 "pmaxsh\t%0,%1,%2" 417 [(set_attr "type" "fadd")]) 418 419(define_expand "smax<mode>3" 420 [(match_operand:VWB 0 "register_operand" "") 421 (match_operand:VWB 1 "register_operand" "") 422 (match_operand:VWB 2 "register_operand" "")] 423 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 424{ 425 mips_expand_vec_minmax (operands[0], operands[1], operands[2], 426 gen_loongson_pcmpgt<V_suffix>, false); 427 DONE; 428}) 429 430;; Maximum of unsigned bytes. 431(define_insn "umaxv8qi3" 432 [(set (match_operand:V8QI 0 "register_operand" "=f") 433 (umax:V8QI (match_operand:V8QI 1 "register_operand" "f") 434 (match_operand:V8QI 2 "register_operand" "f")))] 435 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 436 "pmaxub\t%0,%1,%2" 437 [(set_attr "type" "fadd")]) 438 439;; Minimum of signed halfwords. 440(define_insn "sminv4hi3" 441 [(set (match_operand:V4HI 0 "register_operand" "=f") 442 (smin:V4HI (match_operand:V4HI 1 "register_operand" "f") 443 (match_operand:V4HI 2 "register_operand" "f")))] 444 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 445 "pminsh\t%0,%1,%2" 446 [(set_attr "type" "fadd")]) 447 448(define_expand "smin<mode>3" 449 [(match_operand:VWB 0 "register_operand" "") 450 (match_operand:VWB 1 "register_operand" "") 451 (match_operand:VWB 2 "register_operand" "")] 452 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 453{ 454 mips_expand_vec_minmax (operands[0], operands[1], operands[2], 455 gen_loongson_pcmpgt<V_suffix>, true); 456 DONE; 457}) 458 459;; Minimum of unsigned bytes. 460(define_insn "uminv8qi3" 461 [(set (match_operand:V8QI 0 "register_operand" "=f") 462 (umin:V8QI (match_operand:V8QI 1 "register_operand" "f") 463 (match_operand:V8QI 2 "register_operand" "f")))] 464 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 465 "pminub\t%0,%1,%2" 466 [(set_attr "type" "fadd")]) 467 468;; Move byte mask. 469(define_insn "loongson_pmovmsk<V_suffix>" 470 [(set (match_operand:VB 0 "register_operand" "=f") 471 (unspec:VB [(match_operand:VB 1 "register_operand" "f")] 472 UNSPEC_LOONGSON_PMOVMSK))] 473 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 474 "pmovmsk<V_suffix>\t%0,%1" 475 [(set_attr "type" "fabs")]) 476 477;; Multiply unsigned integers and store high result. 478(define_insn "umul<mode>3_highpart" 479 [(set (match_operand:VH 0 "register_operand" "=f") 480 (unspec:VH [(match_operand:VH 1 "register_operand" "f") 481 (match_operand:VH 2 "register_operand" "f")] 482 UNSPEC_LOONGSON_PMULHU))] 483 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 484 "pmulhu<V_suffix>\t%0,%1,%2" 485 [(set_attr "type" "fmul")]) 486 487;; Multiply signed integers and store high result. 488(define_insn "smul<mode>3_highpart" 489 [(set (match_operand:VH 0 "register_operand" "=f") 490 (unspec:VH [(match_operand:VH 1 "register_operand" "f") 491 (match_operand:VH 2 "register_operand" "f")] 492 UNSPEC_LOONGSON_PMULH))] 493 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 494 "pmulh<V_suffix>\t%0,%1,%2" 495 [(set_attr "type" "fmul")]) 496 497;; Multiply signed integers and store low result. 498(define_insn "mul<mode>3" 499 [(set (match_operand:VH 0 "register_operand" "=f") 500 (mult:VH (match_operand:VH 1 "register_operand" "f") 501 (match_operand:VH 2 "register_operand" "f")))] 502 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 503 "pmull<V_suffix>\t%0,%1,%2" 504 [(set_attr "type" "fmul")]) 505 506;; Multiply unsigned word integers. 507(define_insn "loongson_pmulu<V_suffix>" 508 [(set (match_operand:DI 0 "register_operand" "=f") 509 (unspec:DI [(match_operand:VW 1 "register_operand" "f") 510 (match_operand:VW 2 "register_operand" "f")] 511 UNSPEC_LOONGSON_PMULU))] 512 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 513 "pmulu<V_suffix>\t%0,%1,%2" 514 [(set_attr "type" "fmul")]) 515 516;; Absolute difference. 517(define_insn "loongson_pasubub" 518 [(set (match_operand:VB 0 "register_operand" "=f") 519 (unspec:VB [(match_operand:VB 1 "register_operand" "f") 520 (match_operand:VB 2 "register_operand" "f")] 521 UNSPEC_LOONGSON_PASUBUB))] 522 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 523 "pasubub\t%0,%1,%2" 524 [(set_attr "type" "fadd")]) 525 526;; Sum of unsigned byte integers. 527(define_insn "loongson_biadd" 528 [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f") 529 (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f")] 530 UNSPEC_LOONGSON_BIADD))] 531 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 532 "biadd\t%0,%1" 533 [(set_attr "type" "fabs")]) 534 535(define_insn "reduc_uplus_v8qi" 536 [(set (match_operand:V8QI 0 "register_operand" "=f") 537 (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "f")] 538 UNSPEC_LOONGSON_BIADD))] 539 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 540 "biadd\t%0,%1" 541 [(set_attr "type" "fabs")]) 542 543;; Sum of absolute differences. 544(define_insn "loongson_psadbh" 545 [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f") 546 (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f") 547 (match_operand:VB 2 "register_operand" "f")] 548 UNSPEC_LOONGSON_PSADBH))] 549 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 550 "pasubub\t%0,%1,%2;biadd\t%0,%0" 551 [(set_attr "type" "fadd")]) 552 553;; Shuffle halfwords. 554(define_insn "loongson_pshufh" 555 [(set (match_operand:VH 0 "register_operand" "=f") 556 (unspec:VH [(match_operand:VH 1 "register_operand" "f") 557 (match_operand:SI 2 "register_operand" "f")] 558 UNSPEC_LOONGSON_PSHUFH))] 559 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 560 "pshufh\t%0,%1,%2" 561 [(set_attr "type" "fmul")]) 562 563;; Shift left logical. 564(define_insn "ashl<mode>3" 565 [(set (match_operand:VWH 0 "register_operand" "=f") 566 (ashift:VWH (match_operand:VWH 1 "register_operand" "f") 567 (match_operand:SI 2 "register_operand" "f")))] 568 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 569 "psll<V_suffix>\t%0,%1,%2" 570 [(set_attr "type" "fcvt")]) 571 572;; Shift right arithmetic. 573(define_insn "ashr<mode>3" 574 [(set (match_operand:VWH 0 "register_operand" "=f") 575 (ashiftrt:VWH (match_operand:VWH 1 "register_operand" "f") 576 (match_operand:SI 2 "register_operand" "f")))] 577 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 578 "psra<V_suffix>\t%0,%1,%2" 579 [(set_attr "type" "fcvt")]) 580 581;; Shift right logical. 582(define_insn "lshr<mode>3" 583 [(set (match_operand:VWH 0 "register_operand" "=f") 584 (lshiftrt:VWH (match_operand:VWH 1 "register_operand" "f") 585 (match_operand:SI 2 "register_operand" "f")))] 586 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 587 "psrl<V_suffix>\t%0,%1,%2" 588 [(set_attr "type" "fcvt")]) 589 590;; Subtraction, treating overflow by wraparound. 591(define_insn "sub<mode>3" 592 [(set (match_operand:VWHB 0 "register_operand" "=f") 593 (minus:VWHB (match_operand:VWHB 1 "register_operand" "f") 594 (match_operand:VWHB 2 "register_operand" "f")))] 595 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 596 "psub<V_suffix>\t%0,%1,%2" 597 [(set_attr "type" "fadd")]) 598 599;; Subtraction of doubleword integers stored in FP registers. 600;; Overflow is treated by wraparound. 601;; See loongson_paddd for the reason we use 'unspec' rather than 602;; 'minus' here. 603(define_insn "loongson_psubd" 604 [(set (match_operand:DI 0 "register_operand" "=f") 605 (unspec:DI [(match_operand:DI 1 "register_operand" "f") 606 (match_operand:DI 2 "register_operand" "f")] 607 UNSPEC_LOONGSON_PSUBD))] 608 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 609 "psubd\t%0,%1,%2" 610 [(set_attr "type" "fadd")]) 611 612;; Subtraction, treating overflow by signed saturation. 613(define_insn "sssub<mode>3" 614 [(set (match_operand:VHB 0 "register_operand" "=f") 615 (ss_minus:VHB (match_operand:VHB 1 "register_operand" "f") 616 (match_operand:VHB 2 "register_operand" "f")))] 617 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 618 "psubs<V_suffix>\t%0,%1,%2" 619 [(set_attr "type" "fadd")]) 620 621;; Subtraction, treating overflow by unsigned saturation. 622(define_insn "ussub<mode>3" 623 [(set (match_operand:VHB 0 "register_operand" "=f") 624 (us_minus:VHB (match_operand:VHB 1 "register_operand" "f") 625 (match_operand:VHB 2 "register_operand" "f")))] 626 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 627 "psubus<V_suffix>\t%0,%1,%2" 628 [(set_attr "type" "fadd")]) 629 630;; Unpack high data. Recall that Loongson only runs in little-endian. 631(define_insn "loongson_punpckhbh" 632 [(set (match_operand:V8QI 0 "register_operand" "=f") 633 (vec_select:V8QI 634 (vec_concat:V16QI 635 (match_operand:V8QI 1 "register_operand" "f") 636 (match_operand:V8QI 2 "register_operand" "f")) 637 (parallel [(const_int 4) (const_int 12) 638 (const_int 5) (const_int 13) 639 (const_int 6) (const_int 14) 640 (const_int 7) (const_int 15)])))] 641 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 642 "punpckhbh\t%0,%1,%2" 643 [(set_attr "type" "fdiv")]) 644 645(define_insn "loongson_punpckhhw" 646 [(set (match_operand:V4HI 0 "register_operand" "=f") 647 (vec_select:V4HI 648 (vec_concat:V8HI 649 (match_operand:V4HI 1 "register_operand" "f") 650 (match_operand:V4HI 2 "register_operand" "f")) 651 (parallel [(const_int 2) (const_int 6) 652 (const_int 3) (const_int 7)])))] 653 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 654 "punpckhhw\t%0,%1,%2" 655 [(set_attr "type" "fdiv")]) 656 657(define_insn "loongson_punpckhhw_qi" 658 [(set (match_operand:V8QI 0 "register_operand" "=f") 659 (vec_select:V8QI 660 (vec_concat:V16QI 661 (match_operand:V8QI 1 "register_operand" "f") 662 (match_operand:V8QI 2 "register_operand" "f")) 663 (parallel [(const_int 4) (const_int 5) 664 (const_int 12) (const_int 13) 665 (const_int 6) (const_int 7) 666 (const_int 14) (const_int 15)])))] 667 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 668 "punpckhhw\t%0,%1,%2" 669 [(set_attr "type" "fdiv")]) 670 671(define_insn "loongson_punpckhwd" 672 [(set (match_operand:V2SI 0 "register_operand" "=f") 673 (vec_select:V2SI 674 (vec_concat:V4SI 675 (match_operand:V2SI 1 "register_operand" "f") 676 (match_operand:V2SI 2 "register_operand" "f")) 677 (parallel [(const_int 1) (const_int 3)])))] 678 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 679 "punpckhwd\t%0,%1,%2" 680 [(set_attr "type" "fcvt")]) 681 682(define_insn "loongson_punpckhwd_qi" 683 [(set (match_operand:V8QI 0 "register_operand" "=f") 684 (vec_select:V8QI 685 (vec_concat:V16QI 686 (match_operand:V8QI 1 "register_operand" "f") 687 (match_operand:V8QI 2 "register_operand" "f")) 688 (parallel [(const_int 4) (const_int 5) 689 (const_int 6) (const_int 7) 690 (const_int 12) (const_int 13) 691 (const_int 14) (const_int 15)])))] 692 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 693 "punpckhwd\t%0,%1,%2" 694 [(set_attr "type" "fcvt")]) 695 696(define_insn "loongson_punpckhwd_hi" 697 [(set (match_operand:V4HI 0 "register_operand" "=f") 698 (vec_select:V4HI 699 (vec_concat:V8HI 700 (match_operand:V4HI 1 "register_operand" "f") 701 (match_operand:V4HI 2 "register_operand" "f")) 702 (parallel [(const_int 2) (const_int 3) 703 (const_int 6) (const_int 7)])))] 704 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 705 "punpckhwd\t%0,%1,%2" 706 [(set_attr "type" "fcvt")]) 707 708;; Unpack low data. 709(define_insn "loongson_punpcklbh" 710 [(set (match_operand:V8QI 0 "register_operand" "=f") 711 (vec_select:V8QI 712 (vec_concat:V16QI 713 (match_operand:V8QI 1 "register_operand" "f") 714 (match_operand:V8QI 2 "register_operand" "f")) 715 (parallel [(const_int 0) (const_int 8) 716 (const_int 1) (const_int 9) 717 (const_int 2) (const_int 10) 718 (const_int 3) (const_int 11)])))] 719 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 720 "punpcklbh\t%0,%1,%2" 721 [(set_attr "type" "fdiv")]) 722 723(define_insn "loongson_punpcklhw" 724 [(set (match_operand:V4HI 0 "register_operand" "=f") 725 (vec_select:V4HI 726 (vec_concat:V8HI 727 (match_operand:V4HI 1 "register_operand" "f") 728 (match_operand:V4HI 2 "register_operand" "f")) 729 (parallel [(const_int 0) (const_int 4) 730 (const_int 1) (const_int 5)])))] 731 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 732 "punpcklhw\t%0,%1,%2" 733 [(set_attr "type" "fdiv")]) 734 735(define_insn "*loongson_punpcklhw_qi" 736 [(set (match_operand:V8QI 0 "register_operand" "=f") 737 (vec_select:V8QI 738 (vec_concat:V16QI 739 (match_operand:V8QI 1 "register_operand" "f") 740 (match_operand:V8QI 2 "register_operand" "f")) 741 (parallel [(const_int 0) (const_int 1) 742 (const_int 8) (const_int 9) 743 (const_int 2) (const_int 3) 744 (const_int 10) (const_int 11)])))] 745 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 746 "punpcklhw\t%0,%1,%2" 747 [(set_attr "type" "fdiv")]) 748 749(define_insn "loongson_punpcklwd" 750 [(set (match_operand:V2SI 0 "register_operand" "=f") 751 (vec_select:V2SI 752 (vec_concat:V4SI 753 (match_operand:V2SI 1 "register_operand" "f") 754 (match_operand:V2SI 2 "register_operand" "f")) 755 (parallel [(const_int 0) (const_int 2)])))] 756 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 757 "punpcklwd\t%0,%1,%2" 758 [(set_attr "type" "fcvt")]) 759 760(define_insn "*loongson_punpcklwd_qi" 761 [(set (match_operand:V8QI 0 "register_operand" "=f") 762 (vec_select:V8QI 763 (vec_concat:V16QI 764 (match_operand:V8QI 1 "register_operand" "f") 765 (match_operand:V8QI 2 "register_operand" "f")) 766 (parallel [(const_int 0) (const_int 1) 767 (const_int 2) (const_int 3) 768 (const_int 8) (const_int 9) 769 (const_int 10) (const_int 11)])))] 770 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 771 "punpcklwd\t%0,%1,%2" 772 [(set_attr "type" "fcvt")]) 773 774(define_insn "*loongson_punpcklwd_hi" 775 [(set (match_operand:V4HI 0 "register_operand" "=f") 776 (vec_select:V4HI 777 (vec_concat:V8HI 778 (match_operand:V4HI 1 "register_operand" "f") 779 (match_operand:V4HI 2 "register_operand" "f")) 780 (parallel [(const_int 0) (const_int 1) 781 (const_int 4) (const_int 5)])))] 782 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 783 "punpcklwd\t%0,%1,%2" 784 [(set_attr "type" "fcvt")]) 785 786(define_expand "vec_unpacks_lo_<mode>" 787 [(match_operand:<V_stretch_half> 0 "register_operand" "") 788 (match_operand:VHB 1 "register_operand" "")] 789 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 790{ 791 mips_expand_vec_unpack (operands, false, false); 792 DONE; 793}) 794 795(define_expand "vec_unpacks_hi_<mode>" 796 [(match_operand:<V_stretch_half> 0 "register_operand" "") 797 (match_operand:VHB 1 "register_operand" "")] 798 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 799{ 800 mips_expand_vec_unpack (operands, false, true); 801 DONE; 802}) 803 804(define_expand "vec_unpacku_lo_<mode>" 805 [(match_operand:<V_stretch_half> 0 "register_operand" "") 806 (match_operand:VHB 1 "register_operand" "")] 807 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 808{ 809 mips_expand_vec_unpack (operands, true, false); 810 DONE; 811}) 812 813(define_expand "vec_unpacku_hi_<mode>" 814 [(match_operand:<V_stretch_half> 0 "register_operand" "") 815 (match_operand:VHB 1 "register_operand" "")] 816 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 817{ 818 mips_expand_vec_unpack (operands, true, true); 819 DONE; 820}) 821 822;; Whole vector shifts, used for reduction epilogues. 823(define_insn "vec_shl_<mode>" 824 [(set (match_operand:VWHBDI 0 "register_operand" "=f") 825 (unspec:VWHBDI [(match_operand:VWHBDI 1 "register_operand" "f") 826 (match_operand:SI 2 "register_operand" "f")] 827 UNSPEC_LOONGSON_DSLL))] 828 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 829 "dsll\t%0,%1,%2" 830 [(set_attr "type" "fcvt")]) 831 832(define_insn "vec_shr_<mode>" 833 [(set (match_operand:VWHBDI 0 "register_operand" "=f") 834 (unspec:VWHBDI [(match_operand:VWHBDI 1 "register_operand" "f") 835 (match_operand:SI 2 "register_operand" "f")] 836 UNSPEC_LOONGSON_DSRL))] 837 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 838 "dsrl\t%0,%1,%2" 839 [(set_attr "type" "fcvt")]) 840 841(define_insn "vec_loongson_extract_lo_<mode>" 842 [(set (match_operand:<V_inner> 0 "register_operand" "=r") 843 (vec_select:<V_inner> 844 (match_operand:VWHB 1 "register_operand" "f") 845 (parallel [(const_int 0)])))] 846 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 847 "mfc1\t%0,%1" 848 [(set_attr "type" "mfc")]) 849 850(define_expand "reduc_plus_scal_<mode>" 851 [(match_operand:<V_inner> 0 "register_operand" "") 852 (match_operand:VWHB 1 "register_operand" "")] 853 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 854{ 855 rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); 856 mips_expand_vec_reduc (tmp, operands[1], gen_add<mode>3); 857 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp)); 858 DONE; 859}) 860 861(define_expand "reduc_smax_scal_<mode>" 862 [(match_operand:<V_inner> 0 "register_operand" "") 863 (match_operand:VWHB 1 "register_operand" "")] 864 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 865{ 866 rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); 867 mips_expand_vec_reduc (tmp, operands[1], gen_smax<mode>3); 868 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp)); 869 DONE; 870}) 871 872(define_expand "reduc_smin_scal_<mode>" 873 [(match_operand:<V_inner> 0 "register_operand" "") 874 (match_operand:VWHB 1 "register_operand" "")] 875 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 876{ 877 rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); 878 mips_expand_vec_reduc (tmp, operands[1], gen_smin<mode>3); 879 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp)); 880 DONE; 881}) 882 883(define_expand "reduc_umax_scal_<mode>" 884 [(match_operand:<V_inner> 0 "register_operand" "") 885 (match_operand:VB 1 "register_operand" "")] 886 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 887{ 888 rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); 889 mips_expand_vec_reduc (tmp, operands[1], gen_umax<mode>3); 890 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp)); 891 DONE; 892}) 893 894(define_expand "reduc_umin_scal_<mode>" 895 [(match_operand:<V_inner> 0 "register_operand" "") 896 (match_operand:VB 1 "register_operand" "")] 897 "TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI" 898{ 899 rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); 900 mips_expand_vec_reduc (tmp, operands[1], gen_umin<mode>3); 901 emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp)); 902 DONE; 903}) 904