spu-builtins.md 26 KB

;; Copyright (C) 2006-2015 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;

})