diff options
Diffstat (limited to 'gcc/config/mips/loongson.md')
-rw-r--r-- | gcc/config/mips/loongson.md | 437 |
1 files changed, 437 insertions, 0 deletions
diff --git a/gcc/config/mips/loongson.md b/gcc/config/mips/loongson.md new file mode 100644 index 00000000000..5177ae477dc --- /dev/null +++ b/gcc/config/mips/loongson.md @@ -0,0 +1,437 @@ +;; Machine description for ST Microelectronics Loongson-2E/2F. +;; Copyright (C) 2008 Free Software Foundation, Inc. +;; Contributed by CodeSourcery. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +;; Mode iterators and attributes. + +;; 64-bit vectors of bytes. +(define_mode_iterator VB [V8QI]) + +;; 64-bit vectors of halfwords. +(define_mode_iterator VH [V4HI]) + +;; 64-bit vectors of words. +(define_mode_iterator VW [V2SI]) + +;; 64-bit vectors of halfwords and bytes. +(define_mode_iterator VHB [V4HI V8QI]) + +;; 64-bit vectors of words and halfwords. +(define_mode_iterator VWH [V2SI V4HI]) + +;; 64-bit vectors of words, halfwords and bytes. +(define_mode_iterator VWHB [V2SI V4HI V8QI]) + +;; 64-bit vectors of words, halfwords and bytes; and DImode. +(define_mode_iterator VWHBDI [V2SI V4HI V8QI DI]) + +;; The Loongson instruction suffixes corresponding to the modes in the +;; VWHBDI iterator. +(define_mode_attr V_suffix [(V2SI "w") (V4HI "h") (V8QI "b") (DI "d")]) + +;; Given a vector type T, the mode of a vector half the size of T +;; and with the same number of elements. +(define_mode_attr V_squash [(V2SI "V2HI") (V4HI "V4QI")]) + +;; Given a vector type T, the mode of a vector the same size as T +;; but with half as many elements. +(define_mode_attr V_stretch_half [(V2SI "DI") (V4HI "V2SI") (V8QI "V4HI")]) + +;; The Loongson instruction suffixes corresponding to the transformation +;; expressed by V_stretch_half. +(define_mode_attr V_stretch_half_suffix [(V2SI "wd") (V4HI "hw") (V8QI "bh")]) + +;; Given a vector type T, the mode of a vector the same size as T +;; but with twice as many elements. +(define_mode_attr V_squash_double [(V2SI "V4HI") (V4HI "V8QI")]) + +;; The Loongson instruction suffixes corresponding to the conversions +;; specified by V_half_width. +(define_mode_attr V_squash_double_suffix [(V2SI "wh") (V4HI "hb")]) + +;; Move patterns. + +;; Expander to legitimize moves involving values of vector modes. +(define_expand "mov<mode>" + [(set (match_operand:VWHB 0) + (match_operand:VWHB 1))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" +{ + if (mips_legitimize_move (<MODE>mode, operands[0], operands[1])) + DONE; +}) + +;; Handle legitimized moves between values of vector modes. +(define_insn "mov<mode>_internal" + [(set (match_operand:VWHB 0 "nonimmediate_operand" "=m,f,d,f, d, m, d") + (match_operand:VWHB 1 "move_operand" "f,m,f,dYG,dYG,dYG,m"))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + { return mips_output_move (operands[0], operands[1]); } + [(set_attr "type" "fpstore,fpload,mfc,mtc,move,store,load") + (set_attr "mode" "DI")]) + +;; Initialization of a vector. + +(define_expand "vec_init<mode>" + [(set (match_operand:VWHB 0 "register_operand") + (match_operand 1 ""))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" +{ + mips_expand_vector_init (operands[0], operands[1]); + DONE; +}) + +;; Instruction patterns for SIMD instructions. + +;; Pack with signed saturation. +(define_insn "vec_pack_ssat_<mode>" + [(set (match_operand:<V_squash_double> 0 "register_operand" "=f") + (vec_concat:<V_squash_double> + (ss_truncate:<V_squash> + (match_operand:VWH 1 "register_operand" "f")) + (ss_truncate:<V_squash> + (match_operand:VWH 2 "register_operand" "f"))))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "packss<V_squash_double_suffix>\t%0,%1,%2") + +;; Pack with unsigned saturation. +(define_insn "vec_pack_usat_<mode>" + [(set (match_operand:<V_squash_double> 0 "register_operand" "=f") + (vec_concat:<V_squash_double> + (us_truncate:<V_squash> + (match_operand:VH 1 "register_operand" "f")) + (us_truncate:<V_squash> + (match_operand:VH 2 "register_operand" "f"))))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "packus<V_squash_double_suffix>\t%0,%1,%2") + +;; Addition, treating overflow by wraparound. +(define_insn "add<mode>3" + [(set (match_operand:VWHB 0 "register_operand" "=f") + (plus:VWHB (match_operand:VWHB 1 "register_operand" "f") + (match_operand:VWHB 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "padd<V_suffix>\t%0,%1,%2") + +;; Addition of doubleword integers stored in FP registers. +;; Overflow is treated by wraparound. +;; We use 'unspec' instead of 'plus' here to avoid clash with +;; mips.md::add<mode>3. If 'plus' was used, then such instruction +;; would be recognized as adddi3 and reload would make it use +;; GPRs instead of FPRs. +(define_insn "loongson_paddd" + [(set (match_operand:DI 0 "register_operand" "=f") + (unspec:DI [(match_operand:DI 1 "register_operand" "f") + (match_operand:DI 2 "register_operand" "f")] + UNSPEC_LOONGSON_PADDD))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "paddd\t%0,%1,%2") + +;; Addition, treating overflow by signed saturation. +(define_insn "ssadd<mode>3" + [(set (match_operand:VHB 0 "register_operand" "=f") + (ss_plus:VHB (match_operand:VHB 1 "register_operand" "f") + (match_operand:VHB 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "padds<V_suffix>\t%0,%1,%2") + +;; Addition, treating overflow by unsigned saturation. +(define_insn "usadd<mode>3" + [(set (match_operand:VHB 0 "register_operand" "=f") + (us_plus:VHB (match_operand:VHB 1 "register_operand" "f") + (match_operand:VHB 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "paddus<V_suffix>\t%0,%1,%2") + +;; Logical AND NOT. +(define_insn "loongson_pandn_<V_suffix>" + [(set (match_operand:VWHBDI 0 "register_operand" "=f") + (and:VWHBDI + (not:VWHBDI (match_operand:VWHBDI 1 "register_operand" "f")) + (match_operand:VWHBDI 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pandn\t%0,%1,%2") + +;; Average. +(define_insn "loongson_pavg<V_suffix>" + [(set (match_operand:VHB 0 "register_operand" "=f") + (unspec:VHB [(match_operand:VHB 1 "register_operand" "f") + (match_operand:VHB 2 "register_operand" "f")] + UNSPEC_LOONGSON_PAVG))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pavg<V_suffix>\t%0,%1,%2") + +;; Equality test. +(define_insn "loongson_pcmpeq<V_suffix>" + [(set (match_operand:VWHB 0 "register_operand" "=f") + (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f") + (match_operand:VWHB 2 "register_operand" "f")] + UNSPEC_LOONGSON_PCMPEQ))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pcmpeq<V_suffix>\t%0,%1,%2") + +;; Greater-than test. +(define_insn "loongson_pcmpgt<V_suffix>" + [(set (match_operand:VWHB 0 "register_operand" "=f") + (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f") + (match_operand:VWHB 2 "register_operand" "f")] + UNSPEC_LOONGSON_PCMPGT))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pcmpgt<V_suffix>\t%0,%1,%2") + +;; Extract halfword. +(define_insn "loongson_pextr<V_suffix>" + [(set (match_operand:VH 0 "register_operand" "=f") + (unspec:VH [(match_operand:VH 1 "register_operand" "f") + (match_operand:SI 2 "register_operand" "f")] + UNSPEC_LOONGSON_PEXTR))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pextr<V_suffix>\t%0,%1,%2") + +;; Insert halfword. +(define_insn "loongson_pinsr<V_suffix>_0" + [(set (match_operand:VH 0 "register_operand" "=f") + (unspec:VH [(match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")] + UNSPEC_LOONGSON_PINSR_0))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pinsr<V_suffix>_0\t%0,%1,%2") + +(define_insn "loongson_pinsr<V_suffix>_1" + [(set (match_operand:VH 0 "register_operand" "=f") + (unspec:VH [(match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")] + UNSPEC_LOONGSON_PINSR_1))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pinsr<V_suffix>_1\t%0,%1,%2") + +(define_insn "loongson_pinsr<V_suffix>_2" + [(set (match_operand:VH 0 "register_operand" "=f") + (unspec:VH [(match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")] + UNSPEC_LOONGSON_PINSR_2))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pinsr<V_suffix>_2\t%0,%1,%2") + +(define_insn "loongson_pinsr<V_suffix>_3" + [(set (match_operand:VH 0 "register_operand" "=f") + (unspec:VH [(match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")] + UNSPEC_LOONGSON_PINSR_3))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pinsr<V_suffix>_3\t%0,%1,%2") + +;; Multiply and add packed integers. +(define_insn "loongson_pmadd<V_stretch_half_suffix>" + [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f") + (unspec:<V_stretch_half> [(match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")] + UNSPEC_LOONGSON_PMADD))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pmadd<V_stretch_half_suffix>\t%0,%1,%2") + +;; Maximum of signed halfwords. +(define_insn "smax<mode>3" + [(set (match_operand:VH 0 "register_operand" "=f") + (smax:VH (match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pmaxs<V_suffix>\t%0,%1,%2") + +;; Maximum of unsigned bytes. +(define_insn "umax<mode>3" + [(set (match_operand:VB 0 "register_operand" "=f") + (umax:VB (match_operand:VB 1 "register_operand" "f") + (match_operand:VB 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pmaxu<V_suffix>\t%0,%1,%2") + +;; Minimum of signed halfwords. +(define_insn "smin<mode>3" + [(set (match_operand:VH 0 "register_operand" "=f") + (smin:VH (match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pmins<V_suffix>\t%0,%1,%2") + +;; Minimum of unsigned bytes. +(define_insn "umin<mode>3" + [(set (match_operand:VB 0 "register_operand" "=f") + (umin:VB (match_operand:VB 1 "register_operand" "f") + (match_operand:VB 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pminu<V_suffix>\t%0,%1,%2") + +;; Move byte mask. +(define_insn "loongson_pmovmsk<V_suffix>" + [(set (match_operand:VB 0 "register_operand" "=f") + (unspec:VB [(match_operand:VB 1 "register_operand" "f")] + UNSPEC_LOONGSON_PMOVMSK))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pmovmsk<V_suffix>\t%0,%1") + +;; Multiply unsigned integers and store high result. +(define_insn "umul<mode>3_highpart" + [(set (match_operand:VH 0 "register_operand" "=f") + (unspec:VH [(match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")] + UNSPEC_LOONGSON_PMULHU))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pmulhu<V_suffix>\t%0,%1,%2") + +;; Multiply signed integers and store high result. +(define_insn "smul<mode>3_highpart" + [(set (match_operand:VH 0 "register_operand" "=f") + (unspec:VH [(match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")] + UNSPEC_LOONGSON_PMULH))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pmulh<V_suffix>\t%0,%1,%2") + +;; Multiply signed integers and store low result. +(define_insn "loongson_pmull<V_suffix>" + [(set (match_operand:VH 0 "register_operand" "=f") + (unspec:VH [(match_operand:VH 1 "register_operand" "f") + (match_operand:VH 2 "register_operand" "f")] + UNSPEC_LOONGSON_PMULL))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pmull<V_suffix>\t%0,%1,%2") + +;; Multiply unsigned word integers. +(define_insn "loongson_pmulu<V_suffix>" + [(set (match_operand:DI 0 "register_operand" "=f") + (unspec:DI [(match_operand:VW 1 "register_operand" "f") + (match_operand:VW 2 "register_operand" "f")] + UNSPEC_LOONGSON_PMULU))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pmulu<V_suffix>\t%0,%1,%2") + +;; Absolute difference. +(define_insn "loongson_pasubub" + [(set (match_operand:VB 0 "register_operand" "=f") + (unspec:VB [(match_operand:VB 1 "register_operand" "f") + (match_operand:VB 2 "register_operand" "f")] + UNSPEC_LOONGSON_PASUBUB))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pasubub\t%0,%1,%2") + +;; Sum of unsigned byte integers. +(define_insn "reduc_uplus_<mode>" + [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f") + (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f")] + UNSPEC_LOONGSON_BIADD))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "biadd\t%0,%1") + +;; Sum of absolute differences. +(define_insn "loongson_psadbh" + [(set (match_operand:<V_stretch_half> 0 "register_operand" "=f") + (unspec:<V_stretch_half> [(match_operand:VB 1 "register_operand" "f") + (match_operand:VB 2 "register_operand" "f")] + UNSPEC_LOONGSON_PSADBH))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pasubub\t%0,%1,%2;biadd\t%0,%0") + +;; Shuffle halfwords. +(define_insn "loongson_pshufh" + [(set (match_operand:VH 0 "register_operand" "=f") + (unspec:VH [(match_operand:VH 1 "register_operand" "0") + (match_operand:VH 2 "register_operand" "f") + (match_operand:SI 3 "register_operand" "f")] + UNSPEC_LOONGSON_PSHUFH))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "pshufh\t%0,%2,%3") + +;; Shift left logical. +(define_insn "loongson_psll<V_suffix>" + [(set (match_operand:VWH 0 "register_operand" "=f") + (ashift:VWH (match_operand:VWH 1 "register_operand" "f") + (match_operand:SI 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "psll<V_suffix>\t%0,%1,%2") + +;; Shift right arithmetic. +(define_insn "loongson_psra<V_suffix>" + [(set (match_operand:VWH 0 "register_operand" "=f") + (ashiftrt:VWH (match_operand:VWH 1 "register_operand" "f") + (match_operand:SI 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "psra<V_suffix>\t%0,%1,%2") + +;; Shift right logical. +(define_insn "loongson_psrl<V_suffix>" + [(set (match_operand:VWH 0 "register_operand" "=f") + (lshiftrt:VWH (match_operand:VWH 1 "register_operand" "f") + (match_operand:SI 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "psrl<V_suffix>\t%0,%1,%2") + +;; Subtraction, treating overflow by wraparound. +(define_insn "sub<mode>3" + [(set (match_operand:VWHB 0 "register_operand" "=f") + (minus:VWHB (match_operand:VWHB 1 "register_operand" "f") + (match_operand:VWHB 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "psub<V_suffix>\t%0,%1,%2") + +;; Subtraction of doubleword integers stored in FP registers. +;; Overflow is treated by wraparound. +;; See loongson_paddd for the reason we use 'unspec' rather than +;; 'minus' here. +(define_insn "loongson_psubd" + [(set (match_operand:DI 0 "register_operand" "=f") + (unspec:DI [(match_operand:DI 1 "register_operand" "f") + (match_operand:DI 2 "register_operand" "f")] + UNSPEC_LOONGSON_PSUBD))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "psubd\t%0,%1,%2") + +;; Subtraction, treating overflow by signed saturation. +(define_insn "sssub<mode>3" + [(set (match_operand:VHB 0 "register_operand" "=f") + (ss_minus:VHB (match_operand:VHB 1 "register_operand" "f") + (match_operand:VHB 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "psubs<V_suffix>\t%0,%1,%2") + +;; Subtraction, treating overflow by unsigned saturation. +(define_insn "ussub<mode>3" + [(set (match_operand:VHB 0 "register_operand" "=f") + (us_minus:VHB (match_operand:VHB 1 "register_operand" "f") + (match_operand:VHB 2 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "psubus<V_suffix>\t%0,%1,%2") + +;; Unpack high data. +(define_insn "vec_interleave_high<mode>" + [(set (match_operand:VWHB 0 "register_operand" "=f") + (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f") + (match_operand:VWHB 2 "register_operand" "f")] + UNSPEC_LOONGSON_PUNPCKH))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "punpckh<V_stretch_half_suffix>\t%0,%1,%2") + +;; Unpack low data. +(define_insn "vec_interleave_low<mode>" + [(set (match_operand:VWHB 0 "register_operand" "=f") + (unspec:VWHB [(match_operand:VWHB 1 "register_operand" "f") + (match_operand:VWHB 2 "register_operand" "f")] + UNSPEC_LOONGSON_PUNPCKL))] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" + "punpckl<V_stretch_half_suffix>\t%0,%1,%2") |