;; Copyright (C) 2006-2019 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))]
""
"")
(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_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;
})