summaryrefslogtreecommitdiff
path: root/gcc/config/spu/spu-builtins.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/spu/spu-builtins.md')
-rw-r--r--gcc/config/spu/spu-builtins.md142
1 files changed, 112 insertions, 30 deletions
diff --git a/gcc/config/spu/spu-builtins.md b/gcc/config/spu/spu-builtins.md
index 325a80d6b29..ac3a3336106 100644
--- a/gcc/config/spu/spu-builtins.md
+++ b/gcc/config/spu/spu-builtins.md
@@ -527,37 +527,119 @@
[(set_attr "type" "br")])
;; float convert
-(define_insn "spu_csflt"
+(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" "r")
- (match_operand:SI 2 "immediate_operand" "K")] UNSPEC_CSFLT ))]
- ""
- "csflt\t%0,%1,%2"
- [(set_attr "type" "fp7")])
-
-(define_insn "spu_cflts"
- [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
- (unspec:V4SI [(match_operand:V4SF 1 "spu_reg_operand" "r")
- (match_operand:SI 2 "immediate_operand" "J")] UNSPEC_CFLTS ))]
- ""
- "cflts\t%0,%1,%2"
- [(set_attr "type" "fp7")])
-
-(define_insn "spu_cuflt"
- [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
- (unspec:V4SF [(match_operand:V4SI 1 "spu_reg_operand" "r")
- (match_operand:SI 2 "immediate_operand" "K")] UNSPEC_CUFLT ))]
- ""
- "cuflt\t%0,%1,%2"
- [(set_attr "type" "fp7")])
-
-(define_insn "spu_cfltu"
- [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
- (unspec:V4SI [(match_operand:V4SF 1 "spu_reg_operand" "r")
- (match_operand:SI 2 "immediate_operand" "J")] UNSPEC_CFLTU ))]
- ""
- "cfltu\t%0,%1,%2"
- [(set_attr "type" "fp7")])
+ (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" "")