930 lines
28 KiB
Markdown
930 lines
28 KiB
Markdown
;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||
|
||
;; This file 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 of the License, or (at your option)
|
||
;; any later version.
|
||
|
||
;; This file 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/>.
|
||
|
||
|
||
;; This includes expands for all the intrinsics.
|
||
;; spu_expand_builtin looks at the mode of match_operand.
|
||
|
||
|
||
;; load/store
|
||
|
||
(define_expand "spu_lqd"
|
||
[(set (match_operand:TI 0 "spu_reg_operand" "")
|
||
(mem:TI (and:SI (plus:SI (match_operand:SI 1 "spu_reg_operand" "")
|
||
(match_operand:SI 2 "spu_nonmem_operand" ""))
|
||
(const_int -16))))]
|
||
""
|
||
{
|
||
if (GET_CODE (operands[2]) == CONST_INT
|
||
&& (INTVAL (operands[2]) & 15) != 0)
|
||
operands[2] = GEN_INT (INTVAL (operands[2]) & -16);
|
||
if (GET_CODE (operands[2]) != CONST_INT)
|
||
{
|
||
rtx op2 = operands[2];
|
||
operands[2] = force_reg (Pmode, operands[2]);
|
||
if (!ALIGNED_SYMBOL_REF_P (op2))
|
||
emit_insn (gen_andsi3 (operands[2], operands[2], GEN_INT (-16)));
|
||
}
|
||
})
|
||
|
||
(define_expand "spu_lqx"
|
||
[(set (match_operand:TI 0 "spu_reg_operand" "")
|
||
(mem:TI (and:SI (plus:SI (match_operand:SI 1 "spu_reg_operand" "")
|
||
(match_operand:SI 2 "spu_reg_operand" ""))
|
||
(const_int -16))))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_lqa"
|
||
[(set (match_operand:TI 0 "spu_reg_operand" "")
|
||
(mem:TI (and:SI (match_operand:SI 1 "immediate_operand" "")
|
||
(const_int -16))))]
|
||
""
|
||
{
|
||
if (GET_CODE (operands[1]) == CONST_INT
|
||
&& (INTVAL (operands[1]) & 15) != 0)
|
||
operands[1] = GEN_INT (INTVAL (operands[1]) & -16);
|
||
})
|
||
|
||
(define_expand "spu_lqr"
|
||
[(set (match_operand:TI 0 "spu_reg_operand" "")
|
||
(mem:TI (and:SI (match_operand:SI 1 "address_operand" "")
|
||
(const_int -16))))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_stqd"
|
||
[(set (mem:TI (and:SI (plus:SI (match_operand:SI 1 "spu_reg_operand" "")
|
||
(match_operand:SI 2 "spu_nonmem_operand" ""))
|
||
(const_int -16)))
|
||
(match_operand:TI 0 "spu_reg_operand" "r,r"))]
|
||
""
|
||
{
|
||
if (GET_CODE (operands[2]) == CONST_INT
|
||
&& (INTVAL (operands[2]) & 15) != 0)
|
||
operands[2] = GEN_INT (INTVAL (operands[2]) & -16);
|
||
if (GET_CODE (operands[2]) != CONST_INT)
|
||
{
|
||
rtx op2 = operands[2];
|
||
operands[2] = force_reg (Pmode, operands[2]);
|
||
if (!ALIGNED_SYMBOL_REF_P (op2))
|
||
emit_insn (gen_andsi3 (operands[2], operands[2], GEN_INT (-16)));
|
||
}
|
||
})
|
||
|
||
(define_expand "spu_stqx"
|
||
[(set (mem:TI (and:SI (plus:SI (match_operand:SI 1 "spu_reg_operand" "")
|
||
(match_operand:SI 2 "spu_reg_operand" ""))
|
||
(const_int -16)))
|
||
(match_operand:TI 0 "spu_reg_operand" "r"))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_stqa"
|
||
[(set (mem:TI (and:SI (match_operand:SI 1 "immediate_operand" "")
|
||
(const_int -16)))
|
||
(match_operand:TI 0 "spu_reg_operand" "r"))]
|
||
""
|
||
{
|
||
if (GET_CODE (operands[1]) == CONST_INT
|
||
&& (INTVAL (operands[1]) & 15) != 0)
|
||
operands[1] = GEN_INT (INTVAL (operands[1]) & -16);
|
||
})
|
||
|
||
(define_expand "spu_stqr"
|
||
[(set (mem:TI (and:SI (match_operand:SI 1 "address_operand" "")
|
||
(const_int -16)))
|
||
(match_operand:TI 0 "spu_reg_operand" ""))]
|
||
""
|
||
"")
|
||
|
||
|
||
;; generate control word
|
||
|
||
(define_expand "spu_cbx"
|
||
[(set (match_operand:TI 0 "spu_reg_operand" "")
|
||
(unspec:TI [(match_operand:SI 1 "spu_reg_operand" "")
|
||
(match_operand:SI 2 "spu_nonmem_operand" "")
|
||
(const_int 1)] UNSPEC_CPAT))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_chx"
|
||
[(set (match_operand:TI 0 "spu_reg_operand" "")
|
||
(unspec:TI [(match_operand:SI 1 "spu_reg_operand" "")
|
||
(match_operand:SI 2 "spu_nonmem_operand" "")
|
||
(const_int 2)] UNSPEC_CPAT))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_cwx"
|
||
[(set (match_operand:TI 0 "spu_reg_operand" "")
|
||
(unspec:TI [(match_operand:SI 1 "spu_reg_operand" "")
|
||
(match_operand:SI 2 "spu_nonmem_operand" "")
|
||
(const_int 4)] UNSPEC_CPAT))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_cdx"
|
||
[(set (match_operand:TI 0 "spu_reg_operand" "")
|
||
(unspec:TI [(match_operand:SI 1 "spu_reg_operand" "")
|
||
(match_operand:SI 2 "spu_nonmem_operand" "")
|
||
(const_int 8)] UNSPEC_CPAT))]
|
||
""
|
||
"")
|
||
|
||
|
||
|
||
;; Constant formation
|
||
|
||
(define_expand "spu_ilhu"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "")
|
||
(const_vector:V4SI [(match_operand:SI 1 "immediate_operand" "")]))]
|
||
""
|
||
"{ emit_insn(gen_movv4si(operands[0], spu_const(V4SImode, (INTVAL(operands[1]) << 16))));
|
||
DONE;
|
||
}")
|
||
|
||
|
||
;; integer subtract
|
||
(define_expand "spu_sfh"
|
||
[(set (match_operand:V8HI 0 "spu_reg_operand" "")
|
||
(minus:V8HI (match_operand:V8HI 2 "spu_nonmem_operand" "")
|
||
(match_operand:V8HI 1 "spu_reg_operand" "")))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_sf"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "")
|
||
(minus:V4SI (match_operand:V4SI 2 "spu_nonmem_operand" "")
|
||
(match_operand:V4SI 1 "spu_reg_operand" "")))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_sfx"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "")
|
||
(unspec:V4SI [(match_operand:V4SI 2 "spu_reg_operand" "")
|
||
(match_operand:V4SI 1 "spu_reg_operand" "")
|
||
(match_operand:V4SI 3 "spu_reg_operand" "")] UNSPEC_SFX))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_bg"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "")
|
||
(unspec:V4SI [(match_operand:V4SI 2 "spu_reg_operand" "")
|
||
(match_operand:V4SI 1 "spu_reg_operand" "")] UNSPEC_BG))]
|
||
""
|
||
"")
|
||
|
||
(define_expand "spu_bgx"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "")
|
||
(unspec:V4SI [(match_operand:V4SI 2 "spu_reg_operand" "")
|
||
(match_operand:V4SI 1 "spu_reg_operand" "")
|
||
(match_operand:V4SI 3 "spu_reg_operand" "")] UNSPEC_BGX))]
|
||
""
|
||
"")
|
||
|
||
;; integer multiply
|
||
(define_insn "spu_mpy"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r,r")
|
||
(mult:V4SI
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r,r")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 2 "spu_arith_operand" "r,B")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))))]
|
||
""
|
||
"@
|
||
mpy\t%0,%1,%2
|
||
mpyi\t%0,%1,%2"
|
||
[(set_attr "type" "fp7")])
|
||
|
||
(define_insn "spu_mpyu"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r,r")
|
||
(mult:V4SI
|
||
(zero_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r,r")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))
|
||
(zero_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 2 "spu_arith_operand" "r,B")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))))]
|
||
""
|
||
"@
|
||
mpyu\t%0,%1,%2
|
||
mpyui\t%0,%1,%2"
|
||
[(set_attr "type" "fp7")])
|
||
|
||
(define_insn "spu_mpya"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(plus:V4SI
|
||
(mult:V4SI
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 2 "spu_reg_operand" "r")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))
|
||
(match_operand:V4SI 3 "spu_reg_operand" "r")))]
|
||
""
|
||
"mpya\t%0,%1,%2,%3"
|
||
[(set_attr "type" "fp7")])
|
||
|
||
(define_insn "spu_mpyh"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(ashift:V4SI
|
||
(mult:V4SI
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 2 "spu_reg_operand" "r")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))
|
||
(const_vector:V4SI [(const_int 16)(const_int 16)(const_int 16)(const_int 16)])))]
|
||
""
|
||
"mpyh\t%0,%1,%2"
|
||
[(set_attr "type" "fp7")])
|
||
|
||
(define_insn "spu_mpys"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(ashiftrt:V4SI
|
||
(mult:V4SI
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 2 "spu_reg_operand" "r")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))
|
||
(const_vector:V4SI [(const_int 16)(const_int 16)(const_int 16)(const_int 16)])))]
|
||
""
|
||
"mpys\t%0,%1,%2"
|
||
[(set_attr "type" "fp7")])
|
||
|
||
(define_insn "spu_mpyhhu"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(mult:V4SI
|
||
(zero_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
|
||
(zero_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 2 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))))]
|
||
""
|
||
"mpyhhu\t%0,%1,%2"
|
||
[(set_attr "type" "fp7")])
|
||
|
||
(define_insn "spu_mpyhh"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(mult:V4SI
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 2 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))))]
|
||
""
|
||
"mpyhh\t%0,%1,%2"
|
||
[(set_attr "type" "fp7")])
|
||
|
||
(define_insn "spu_mpyhhau"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(plus:V4SI
|
||
(mult:V4SI
|
||
(zero_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
|
||
(zero_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 2 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))))
|
||
(match_operand:V4SI 3 "spu_reg_operand" "0")))]
|
||
""
|
||
"mpyhhau\t%0,%1,%2"
|
||
[(set_attr "type" "fp7")])
|
||
|
||
(define_insn "spu_mpyhha"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(plus:V4SI
|
||
(mult:V4SI
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 2 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))))
|
||
(match_operand:V4SI 3 "spu_reg_operand" "0")))]
|
||
""
|
||
"mpyhha\t%0,%1,%2"
|
||
[(set_attr "type" "fp7")])
|
||
|
||
;; form select mask
|
||
(define_insn "spu_fsmb"
|
||
[(set (match_operand:V16QI 0 "spu_reg_operand" "=r,r")
|
||
(unspec:V16QI [(match_operand:SI 1 "spu_nonmem_operand" "r,MN")] UNSPEC_FSMB))]
|
||
""
|
||
"@
|
||
fsmb\t%0,%1
|
||
fsmbi\t%0,%1"
|
||
[(set_attr "type" "shuf")])
|
||
|
||
(define_insn "spu_fsmh"
|
||
[(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
|
||
(unspec:V8HI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_FSMH))]
|
||
""
|
||
"fsmh\t%0,%1"
|
||
[(set_attr "type" "shuf")])
|
||
|
||
(define_insn "spu_fsm"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(unspec:V4SI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_FSM))]
|
||
""
|
||
"fsm\t%0,%1"
|
||
[(set_attr "type" "shuf")])
|
||
|
||
|
||
;; gather bits
|
||
(define_insn "spu_gbb"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(unspec:V4SI [(match_operand:V16QI 1 "spu_reg_operand" "r")] UNSPEC_GBB))]
|
||
""
|
||
"gbb\t%0,%1"
|
||
[(set_attr "type" "shuf")])
|
||
|
||
(define_insn "spu_gbh"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(unspec:V4SI [(match_operand:V8HI 1 "spu_reg_operand" "r")] UNSPEC_GBH))]
|
||
""
|
||
"gbh\t%0,%1"
|
||
[(set_attr "type" "shuf")])
|
||
|
||
(define_insn "spu_gb"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(unspec:V4SI [(match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_GB))]
|
||
""
|
||
"gb\t%0,%1"
|
||
[(set_attr "type" "shuf")])
|
||
|
||
;; misc byte operations
|
||
(define_insn "spu_avgb"
|
||
[(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
|
||
(unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r")
|
||
(match_operand:V16QI 2 "spu_reg_operand" "r")] UNSPEC_AVGB))]
|
||
""
|
||
"avgb\t%0,%1,%2"
|
||
[(set_attr "type" "fxb")])
|
||
|
||
(define_insn "spu_absdb"
|
||
[(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
|
||
(unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r")
|
||
(match_operand:V16QI 2 "spu_reg_operand" "r")] UNSPEC_ABSDB))]
|
||
""
|
||
"absdb\t%0,%1,%2"
|
||
[(set_attr "type" "fxb")])
|
||
|
||
(define_insn "spu_sumb"
|
||
[(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
|
||
(unspec:V8HI [(match_operand:V16QI 1 "spu_reg_operand" "r")
|
||
(match_operand:V16QI 2 "spu_reg_operand" "r")] UNSPEC_SUMB))]
|
||
""
|
||
"sumb\t%0,%1,%2"
|
||
[(set_attr "type" "fxb")])
|
||
|
||
;; sign extend
|
||
(define_insn "spu_xsbh"
|
||
[(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
|
||
(sign_extend:V8HI
|
||
(vec_select:V8QI
|
||
(match_operand:V16QI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)
|
||
(const_int 9)(const_int 11)(const_int 13)(const_int 15)]))))]
|
||
""
|
||
"xsbh\t%0,%1")
|
||
|
||
(define_insn "spu_xshw"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(sign_extend:V4SI
|
||
(vec_select:V4HI
|
||
(match_operand:V8HI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))]
|
||
""
|
||
"xshw\t%0,%1")
|
||
|
||
(define_insn "spu_xswd"
|
||
[(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
|
||
(sign_extend:V2DI
|
||
(vec_select:V2SI
|
||
(match_operand:V4SI 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 1)(const_int 3)]))))]
|
||
""
|
||
"xswd\t%0,%1")
|
||
|
||
;; or across
|
||
|
||
(define_insn "spu_orx"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(unspec:V4SI [(match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_ORX))]
|
||
""
|
||
"orx\t%0,%1")
|
||
|
||
|
||
;; compare & halt
|
||
(define_insn "spu_heq"
|
||
[(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r,r")
|
||
(match_operand:SI 1 "spu_nonmem_operand" "r,K")] UNSPEC_HEQ)]
|
||
""
|
||
"@
|
||
heq\t%0,%1
|
||
heqi\t%0,%1")
|
||
|
||
(define_insn "spu_hgt"
|
||
[(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r,r")
|
||
(match_operand:SI 1 "spu_nonmem_operand" "r,K")] UNSPEC_HGT)]
|
||
""
|
||
"@
|
||
hgt\t%0,%1
|
||
hgti\t%0,%1")
|
||
|
||
(define_insn "spu_hlgt"
|
||
[(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r,r")
|
||
(match_operand:SI 1 "spu_nonmem_operand" "r,K")] UNSPEC_HLGT)]
|
||
""
|
||
"@
|
||
hlgt\t%0,%1
|
||
hlgti\t%0,%1")
|
||
|
||
;; branches
|
||
|
||
;; The description below hides the fact that bisled conditionally
|
||
;; executes the call depending on the value in channel 0. This was
|
||
;; done so that the description would conform to the format of a call
|
||
;; insn. Otherwise (if this were not part of call insn), the link
|
||
;; register, $lr, would not be saved/restored in the prologue/epilogue.
|
||
|
||
(define_insn "spu_bisled"
|
||
[(parallel
|
||
[(call (mem:QI (match_operand:SI 0 "spu_reg_operand" "r"))
|
||
(const_int 0))
|
||
(clobber (reg:SI 0))
|
||
(clobber (reg:SI 130))
|
||
(use (match_operand:SI 1 "address_operand" ""))
|
||
(use (const_int 0))])]
|
||
""
|
||
"bisled\t$lr,%0"
|
||
[(set_attr "type" "br")])
|
||
|
||
(define_insn "spu_bisledd"
|
||
[(parallel
|
||
[(call (mem:QI (match_operand:SI 0 "spu_reg_operand" "r"))
|
||
(const_int 0))
|
||
(clobber (reg:SI 0))
|
||
(clobber (reg:SI 130))
|
||
(use (match_operand:SI 1 "address_operand" ""))
|
||
(use (const_int 1))])]
|
||
""
|
||
"bisledd\t$lr,%0"
|
||
[(set_attr "type" "br")])
|
||
|
||
(define_insn "spu_bislede"
|
||
[(parallel
|
||
[(call (mem:QI (match_operand:SI 0 "spu_reg_operand" "r"))
|
||
(const_int 0))
|
||
(clobber (reg:SI 0))
|
||
(clobber (reg:SI 130))
|
||
(use (match_operand:SI 1 "address_operand" ""))
|
||
(use (const_int 2))])]
|
||
""
|
||
"bislede\t$lr,%0"
|
||
[(set_attr "type" "br")])
|
||
|
||
;; float convert
|
||
(define_expand "spu_csflt"
|
||
[(set (match_operand:V4SF 0 "spu_reg_operand")
|
||
(unspec:V4SF [(match_operand:V4SI 1 "spu_reg_operand")
|
||
(match_operand:SI 2 "spu_nonmem_operand")] 0 ))]
|
||
""
|
||
{
|
||
if (GET_CODE (operands[2]) == CONST_INT
|
||
&& (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127))
|
||
{
|
||
error ("spu_convtf expects an integer literal in the range [0, 127].");
|
||
operands[2] = force_reg (SImode, operands[2]);
|
||
}
|
||
if (GET_CODE (operands[2]) != CONST_INT)
|
||
{
|
||
rtx exp2;
|
||
rtx cnv = gen_reg_rtx (V4SFmode);
|
||
rtx scale = gen_reg_rtx (SImode);
|
||
rtx op2 = force_reg (SImode, operands[2]);
|
||
rtx m1 = spu_gen_exp2 (V4SFmode, GEN_INT (-1));
|
||
emit_insn (gen_subsi3 (scale, const1_rtx, op2));
|
||
exp2 = spu_gen_exp2 (V4SFmode, scale);
|
||
emit_insn (gen_floatv4siv4sf2_mul (cnv, operands[1], m1));
|
||
emit_insn (gen_mulv4sf3 (operands[0], cnv, exp2));
|
||
}
|
||
else
|
||
{
|
||
rtx exp2 = spu_gen_exp2 (V4SFmode, operands[2]);
|
||
emit_insn (gen_floatv4siv4sf2_div (operands[0], operands[1], exp2));
|
||
}
|
||
DONE;
|
||
})
|
||
|
||
(define_expand "spu_cflts"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand")
|
||
(unspec:V4SI [(match_operand:V4SF 1 "spu_reg_operand")
|
||
(match_operand:SI 2 "spu_nonmem_operand")] 0 ))]
|
||
""
|
||
{
|
||
rtx exp2;
|
||
if (GET_CODE (operands[2]) == CONST_INT
|
||
&& (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127))
|
||
{
|
||
error ("spu_convts expects an integer literal in the range [0, 127].");
|
||
operands[2] = force_reg (SImode, operands[2]);
|
||
}
|
||
exp2 = spu_gen_exp2 (V4SFmode, operands[2]);
|
||
if (GET_CODE (operands[2]) != CONST_INT)
|
||
{
|
||
rtx mul = gen_reg_rtx (V4SFmode);
|
||
emit_insn (gen_mulv4sf3 (mul, operands[1], exp2));
|
||
emit_insn (gen_fix_truncv4sfv4si2 (operands[0], mul));
|
||
}
|
||
else
|
||
emit_insn (gen_fix_truncv4sfv4si2_mul (operands[0], operands[1], exp2));
|
||
DONE;
|
||
})
|
||
|
||
(define_expand "spu_cuflt"
|
||
[(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
|
||
(unspec:V4SF [(match_operand:V4SI 1 "spu_reg_operand")
|
||
(match_operand:SI 2 "spu_nonmem_operand")] 0 ))]
|
||
""
|
||
{
|
||
if (GET_CODE (operands[2]) == CONST_INT
|
||
&& (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127))
|
||
{
|
||
error ("spu_convtf expects an integer literal in the range [0, 127].");
|
||
operands[2] = force_reg (SImode, operands[2]);
|
||
}
|
||
if (GET_CODE (operands[2]) != CONST_INT)
|
||
{
|
||
rtx exp2;
|
||
rtx cnv = gen_reg_rtx (V4SFmode);
|
||
rtx scale = gen_reg_rtx (SImode);
|
||
rtx op2 = force_reg (SImode, operands[2]);
|
||
rtx m1 = spu_gen_exp2 (V4SFmode, GEN_INT (-1));
|
||
emit_insn (gen_subsi3 (scale, const1_rtx, op2));
|
||
exp2 = spu_gen_exp2 (V4SFmode, scale);
|
||
emit_insn (gen_floatunsv4siv4sf2_mul (cnv, operands[1], m1));
|
||
emit_insn (gen_mulv4sf3 (operands[0], cnv, exp2));
|
||
}
|
||
else
|
||
{
|
||
rtx exp2 = spu_gen_exp2 (V4SFmode, operands[2]);
|
||
emit_insn (gen_floatunsv4siv4sf2_div (operands[0], operands[1], exp2));
|
||
}
|
||
DONE;
|
||
})
|
||
|
||
(define_expand "spu_cfltu"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand")
|
||
(unspec:V4SI [(match_operand:V4SF 1 "spu_reg_operand")
|
||
(match_operand:SI 2 "spu_nonmem_operand")] 0 ))]
|
||
""
|
||
{
|
||
rtx exp2;
|
||
if (GET_CODE (operands[2]) == CONST_INT
|
||
&& (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127))
|
||
{
|
||
error ("spu_convtu expects an integer literal in the range [0, 127].");
|
||
operands[2] = force_reg (SImode, operands[2]);
|
||
}
|
||
exp2 = spu_gen_exp2 (V4SFmode, operands[2]);
|
||
if (GET_CODE (operands[2]) != CONST_INT)
|
||
{
|
||
rtx mul = gen_reg_rtx (V4SFmode);
|
||
emit_insn (gen_mulv4sf3 (mul, operands[1], exp2));
|
||
emit_insn (gen_fixuns_truncv4sfv4si2 (operands[0], mul));
|
||
}
|
||
else
|
||
emit_insn (gen_fixuns_truncv4sfv4si2_mul (operands[0], operands[1], exp2));
|
||
DONE;
|
||
})
|
||
|
||
(define_expand "spu_frds"
|
||
[(set (match_operand:V4SF 0 "spu_reg_operand" "")
|
||
(vec_select:V4SF
|
||
(vec_concat:V4SF
|
||
(float_truncate:V2SF (match_operand:V2DF 1 "spu_reg_operand" ""))
|
||
(match_dup:V2SF 2))
|
||
(parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
|
||
""
|
||
"operands[2] = spu_const(V2SFmode, 0);")
|
||
|
||
(define_insn "_frds"
|
||
[(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
|
||
(vec_select:V4SF
|
||
(vec_concat:V4SF
|
||
(float_truncate:V2SF (match_operand:V2DF 1 "spu_reg_operand" "r"))
|
||
(match_operand:V2SF 2 "vec_imm_operand" "i"))
|
||
(parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
|
||
""
|
||
"frds\t%0,%1"
|
||
[(set_attr "type" "fpd")])
|
||
|
||
(define_insn "spu_fesd"
|
||
[(set (match_operand:V2DF 0 "spu_reg_operand" "=r")
|
||
(float_extend:V2DF
|
||
(vec_select:V2SF
|
||
(match_operand:V4SF 1 "spu_reg_operand" "r")
|
||
(parallel [(const_int 0)(const_int 2)]))))]
|
||
""
|
||
"fesd\t%0,%1"
|
||
[(set_attr "type" "fpd")])
|
||
|
||
;; control
|
||
(define_insn "spu_stop"
|
||
[(unspec_volatile [(match_operand:SI 0 "immediate_operand" "M")] UNSPEC_STOP)]
|
||
""
|
||
"stop\t%0"
|
||
[(set_attr "type" "br")])
|
||
|
||
(define_insn "spu_stopd"
|
||
[(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r")
|
||
(match_operand:SI 1 "spu_reg_operand" "r")
|
||
(match_operand:SI 2 "spu_reg_operand" "r")] UNSPEC_STOPD)]
|
||
""
|
||
"stopd\t%0,%1,%2"
|
||
[(set_attr "type" "br")])
|
||
|
||
;; interrupt disable/enable
|
||
(define_expand "spu_idisable"
|
||
[(parallel
|
||
[(unspec_volatile [(const_int 0)] UNSPEC_SET_INTR)
|
||
(clobber (match_dup:SI 0))
|
||
(clobber (mem:BLK (scratch)))])]
|
||
""
|
||
"operands[0] = gen_reg_rtx (SImode);")
|
||
|
||
(define_expand "spu_ienable"
|
||
[(parallel
|
||
[(unspec_volatile [(const_int 1)] UNSPEC_SET_INTR)
|
||
(clobber (match_dup:SI 0))
|
||
(clobber (mem:BLK (scratch)))])]
|
||
""
|
||
"operands[0] = gen_reg_rtx (SImode);")
|
||
|
||
(define_insn "set_intr"
|
||
[(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR)
|
||
(clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
|
||
(clobber (mem:BLK (scratch)))]
|
||
"! flag_pic"
|
||
"ila\t%0,.+8\;bi%I1\t%0"
|
||
[(set_attr "length" "8")
|
||
(set_attr "type" "multi0")])
|
||
|
||
(define_insn "set_intr_pic"
|
||
[(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR)
|
||
(clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
|
||
(clobber (mem:BLK (scratch)))]
|
||
"flag_pic"
|
||
"brsl\t%0,.+4\;ai\t%0,%0,8\;bi%I1\t%0"
|
||
[(set_attr "length" "12")
|
||
(set_attr "type" "multi1")])
|
||
|
||
(define_insn "set_intr_cc"
|
||
[(cond_exec (match_operator 1 "branch_comparison_operator"
|
||
[(match_operand 2 "spu_reg_operand" "r")
|
||
(const_int 0)])
|
||
(parallel [(unspec_volatile [(match_operand:SI 3 "const_int_operand" "i")] UNSPEC_SET_INTR)
|
||
(clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
|
||
(clobber (mem:BLK (scratch)))]))]
|
||
"! flag_pic"
|
||
"ila\t%0,.+8\;bi%b2%b1z%I3\t%2,%0"
|
||
[(set_attr "length" "8")
|
||
(set_attr "type" "multi0")])
|
||
|
||
(define_insn "set_intr_cc_pic"
|
||
[(cond_exec (match_operator 1 "branch_comparison_operator"
|
||
[(match_operand 2 "spu_reg_operand" "r")
|
||
(const_int 0)])
|
||
(parallel [(unspec_volatile [(match_operand:SI 3 "const_int_operand" "i")] UNSPEC_SET_INTR)
|
||
(clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
|
||
(clobber (mem:BLK (scratch)))]))]
|
||
"flag_pic"
|
||
"brsl\t%0,.+4\;ai\t%0,%0,8\;bi%b2%b1z%I3\t%2,%0"
|
||
[(set_attr "length" "12")
|
||
(set_attr "type" "multi1")])
|
||
|
||
(define_insn "set_intr_return"
|
||
[(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")] UNSPEC_SET_INTR)
|
||
(return)]
|
||
""
|
||
"bi%I0\t$lr"
|
||
[(set_attr "type" "br")])
|
||
|
||
(define_peephole2
|
||
[(parallel
|
||
[(unspec_volatile [(match_operand:SI 0 "const_int_operand")] UNSPEC_SET_INTR)
|
||
(clobber (match_operand:SI 1 "spu_reg_operand"))
|
||
(clobber (mem:BLK (scratch)))])
|
||
(use (reg:SI 0))
|
||
(return)]
|
||
""
|
||
[(use (reg:SI 0))
|
||
(parallel
|
||
[(unspec_volatile [(match_dup:SI 0)] UNSPEC_SET_INTR)
|
||
(return)])]
|
||
"")
|
||
|
||
;; special purpose registers
|
||
(define_insn "spu_fscrrd"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(unspec_volatile:V4SI [(const_int 6)] UNSPEC_FSCRRD))]
|
||
""
|
||
"fscrrd\t%0"
|
||
[(set_attr "type" "spr")])
|
||
|
||
(define_insn "spu_fscrwr"
|
||
[(unspec_volatile [(match_operand:V4SI 0 "spu_reg_operand" "r")] UNSPEC_FSCRWR)]
|
||
""
|
||
"fscrwr\t$0,%0"
|
||
[(set_attr "type" "spr")])
|
||
|
||
(define_insn "spu_mfspr"
|
||
[(set (match_operand:SI 0 "spu_reg_operand" "=r")
|
||
(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_MFSPR))]
|
||
""
|
||
"mfspr\t%0,$sp%1"
|
||
[(set_attr "type" "spr")])
|
||
|
||
(define_insn "spu_mtspr"
|
||
[(unspec_volatile [(match_operand:SI 0 "immediate_operand" "J")
|
||
(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_MTSPR)]
|
||
""
|
||
"mtspr\t$sp%0,%1"
|
||
[(set_attr "type" "spr")])
|
||
|
||
;; channels
|
||
(define_expand "spu_rdch"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "")
|
||
(unspec_volatile:V4SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_RDCH))]
|
||
""
|
||
"{
|
||
if (spu_safe_dma (INTVAL (operands[1])))
|
||
{
|
||
emit_insn (gen_spu_rdch_clobber (operands[0], operands[1]));
|
||
DONE;
|
||
}
|
||
}")
|
||
|
||
(define_expand "spu_rchcnt"
|
||
[(set (match_operand:SI 0 "spu_reg_operand" "")
|
||
(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_RCHCNT))]
|
||
""
|
||
"{
|
||
if (spu_safe_dma (INTVAL (operands[1])))
|
||
{
|
||
emit_insn (gen_spu_rchcnt_clobber (operands[0], operands[1]));
|
||
DONE;
|
||
}
|
||
}")
|
||
|
||
(define_expand "spu_wrch"
|
||
[(unspec_volatile [(match_operand:SI 0 "immediate_operand" "")
|
||
(match_operand:V4SI 1 "spu_reg_operand" "")] UNSPEC_WRCH)]
|
||
""
|
||
"{
|
||
if (spu_safe_dma (INTVAL (operands[0])))
|
||
{
|
||
emit_insn (gen_spu_wrch_clobber (operands[0], operands[1]));
|
||
DONE;
|
||
}
|
||
}")
|
||
|
||
(define_insn "spu_rdch_noclobber"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(unspec_volatile:V4SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RDCH))]
|
||
""
|
||
"rdch\t%0,$ch%1"
|
||
[(set_attr "type" "spr")])
|
||
|
||
(define_insn "spu_rchcnt_noclobber"
|
||
[(set (match_operand:SI 0 "spu_reg_operand" "=r")
|
||
(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RCHCNT))]
|
||
""
|
||
"rchcnt\t%0,$ch%1"
|
||
[(set_attr "type" "spr")])
|
||
|
||
(define_insn "spu_wrch_noclobber"
|
||
[(unspec_volatile [(match_operand:SI 0 "immediate_operand" "J")
|
||
(match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_WRCH)]
|
||
""
|
||
"wrch\t$ch%0,%1"
|
||
[(set_attr "type" "spr")])
|
||
|
||
(define_insn "spu_rdch_clobber"
|
||
[(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
|
||
(unspec_volatile:V4SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RDCH))
|
||
(clobber (mem:BLK (scratch)))]
|
||
""
|
||
"rdch\t%0,$ch%1"
|
||
[(set_attr "type" "spr")])
|
||
|
||
(define_insn "spu_rchcnt_clobber"
|
||
[(set (match_operand:SI 0 "spu_reg_operand" "=r")
|
||
(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RCHCNT))
|
||
(clobber (mem:BLK (scratch)))]
|
||
""
|
||
"rchcnt\t%0,$ch%1"
|
||
[(set_attr "type" "spr")])
|
||
|
||
(define_insn "spu_wrch_clobber"
|
||
[(unspec_volatile [(match_operand:SI 0 "immediate_operand" "J")
|
||
(match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_WRCH)
|
||
(clobber (mem:BLK (scratch)))]
|
||
""
|
||
"wrch\t$ch%0,%1"
|
||
[(set_attr "type" "spr")])
|
||
|
||
(define_expand "spu_splats"
|
||
[(set (match_operand 0 "spu_reg_operand" "")
|
||
(vec_duplicate (match_operand 1 "spu_nonmem_operand" "")))]
|
||
""
|
||
{
|
||
spu_builtin_splats(operands);
|
||
DONE;
|
||
})
|
||
|
||
(define_expand "spu_extract"
|
||
[(set (match_operand 0 "spu_reg_operand" "")
|
||
(unspec [(match_operand 1 "spu_reg_operand" "")
|
||
(match_operand 2 "spu_nonmem_operand" "")] 0))]
|
||
""
|
||
{
|
||
spu_builtin_extract (operands);
|
||
DONE;
|
||
})
|
||
|
||
(define_expand "spu_insert"
|
||
[(set (match_operand 0 "spu_reg_operand" "")
|
||
(unspec [(match_operand 1 "spu_reg_operand" "")
|
||
(match_operand 2 "spu_reg_operand" "")
|
||
(match_operand:SI 3 "spu_nonmem_operand" "")] 0))]
|
||
""
|
||
{
|
||
spu_builtin_insert(operands);
|
||
DONE;
|
||
})
|
||
|
||
(define_expand "spu_promote"
|
||
[(set (match_operand 0 "spu_reg_operand" "")
|
||
(unspec [(match_operand 1 "spu_reg_operand" "")
|
||
(match_operand:SI 2 "immediate_operand" "")] 0))]
|
||
""
|
||
{
|
||
spu_builtin_promote(operands);
|
||
DONE;
|
||
})
|
||
|
||
;; Currently doing nothing with this but expanding its args.
|
||
(define_expand "spu_align_hint"
|
||
[(unspec [(match_operand:SI 0 "address_operand" "")
|
||
(match_operand:SI 1 "immediate_operand" "")
|
||
(match_operand:SI 2 "immediate_operand" "")] 0)]
|
||
""
|
||
{
|
||
DONE;
|
||
})
|
||
|