rt_gccstream/gcc/config/mips/loongson.md

18 KiB

;; Machine description for ST Microelectronics Loongson-2E/2F. ;; Copyright (C) 2008, 2009 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" [(set (match_operand:VWHB 0) (match_operand:VWHB 1))] "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" { if (mips_legitimize_move (mode, operands[0], operands[1])) DONE; })

;; Handle legitimized moves between values of vector modes. (define_insn "mov_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 "move_type" "fpstore,fpload,mfc,mtc,move,store,load") (set_attr "mode" "DI")])

;; Initialization of a vector.

(define_expand "vec_init" [(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_" [(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" [(set_attr "type" "fmul")])

;; Pack with unsigned saturation. (define_insn "vec_pack_usat_" [(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" [(set_attr "type" "fmul")])

;; Addition, treating overflow by wraparound. (define_insn "add3" [(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" [(set_attr "type" "fadd")])

;; 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::add3. 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" [(set_attr "type" "fadd")])

;; Addition, treating overflow by signed saturation. (define_insn "ssadd3" [(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" [(set_attr "type" "fadd")])

;; Addition, treating overflow by unsigned saturation. (define_insn "usadd3" [(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" [(set_attr "type" "fadd")])

;; 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" [(set_attr "type" "fmul")])

;; 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" [(set_attr "type" "fadd")])

;; 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" [(set_attr "type" "fadd")])

;; 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" [(set_attr "type" "fadd")])

;; 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" [(set_attr "type" "fmul")])

;; 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" [(set_attr "type" "fdiv")])

(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" [(set_attr "type" "fdiv")])

(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" [(set_attr "type" "fdiv")])

(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" [(set_attr "type" "fdiv")])

;; 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" [(set_attr "type" "fmul")])

;; Maximum of signed halfwords. (define_insn "smax3" [(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" [(set_attr "type" "fadd")])

;; Maximum of unsigned bytes. (define_insn "umax3" [(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" [(set_attr "type" "fadd")])

;; Minimum of signed halfwords. (define_insn "smin3" [(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" [(set_attr "type" "fadd")])

;; Minimum of unsigned bytes. (define_insn "umin3" [(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" [(set_attr "type" "fadd")])

;; 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" [(set_attr "type" "fabs")])

;; Multiply unsigned integers and store high result. (define_insn "umul3_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" [(set_attr "type" "fmul")])

;; Multiply signed integers and store high result. (define_insn "smul3_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" [(set_attr "type" "fmul")])

;; 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" [(set_attr "type" "fmul")])

;; 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" [(set_attr "type" "fmul")])

;; 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" [(set_attr "type" "fadd")])

;; Sum of unsigned byte integers. (define_insn "loongson_biadd" [(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" [(set_attr "type" "fabs")])

;; 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" [(set_attr "type" "fadd")])

;; 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" [(set_attr "type" "fmul")])

;; 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" [(set_attr "type" "fmul")])

;; 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" [(set_attr "type" "fdiv")])

;; 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" [(set_attr "type" "fdiv")])

;; Subtraction, treating overflow by wraparound. (define_insn "sub3" [(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" [(set_attr "type" "fadd")])

;; 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" [(set_attr "type" "fadd")])

;; Subtraction, treating overflow by signed saturation. (define_insn "sssub3" [(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" [(set_attr "type" "fadd")])

;; Subtraction, treating overflow by unsigned saturation. (define_insn "ussub3" [(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" [(set_attr "type" "fadd")])

;; Unpack high data. (define_insn "vec_interleave_high" [(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" [(set_attr "type" "fdiv")])

;; Unpack low data. (define_insn "vec_interleave_low" [(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" [(set_attr "type" "fdiv")])

;; Integer division and modulus.

(define_insn "div3" [(set (match_operand:GPR 0 "register_operand" "=&d") (any_div:GPR (match_operand:GPR 1 "register_operand" "d") (match_operand:GPR 2 "register_operand" "d")))] "TARGET_LOONGSON_2EF" { return mips_output_division ("div.g\t%0,%1,%2", operands); } [(set_attr "type" "idiv3") (set_attr "mode" "")])

(define_insn "mod3" [(set (match_operand:GPR 0 "register_operand" "=&d") (any_mod:GPR (match_operand:GPR 1 "register_operand" "d") (match_operand:GPR 2 "register_operand" "d")))] "TARGET_LOONGSON_2EF" { return mips_output_division ("mod.g\t%0,%1,%2", operands); } [(set_attr "type" "idiv3") (set_attr "mode" "")])