summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Oliveira <igor.oliveira@openbossa.org>2010-09-28 15:30:27 -0400
committerIgor Oliveira <igor.oliveira@openbossa.org>2010-09-29 23:07:26 -0400
commit964e23044eb741cbe6f2a6fd888a0fe37fc6052d (patch)
tree1df74895749a0b91dd15523917d53eae443e1054
parent081d0529b4cabf22229030052d422af0bff2c82b (diff)
llvmpipe: add initial support to double opcodes in llvmpipe.
- implement DMUL opcode
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index 441aebae29..70330dc448 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -963,6 +963,68 @@ emit_kil(
lp_build_mask_update(bld->mask, mask);
}
+static LLVMValueRef
+lp_cast_to_double(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ struct lp_type type;
+ LLVMValueRef res;
+ LLVMTypeRef vec_type;
+ LLVMTypeRef vec_double_type;
+
+ type = lp_type_uint_vec(64);
+ vec_type = lp_build_vec_type(type);
+
+ a = LLVMBuildBitCast(bld->builder, a, vec_type, "");
+ b = LLVMBuildBitCast(bld->builder, b, vec_type, "");
+
+ res = LLVMBuildShl(bld->builder, a, lp_build_const_int_vec(type, 32),"");
+ res = LLVMBuildOr(bld->builder, res, b, "");
+
+ a = LLVMBuildBitCast(bld->builder, a, bld->vec_type, "");
+ b = LLVMBuildBitCast(bld->builder, b, bld->vec_type, "");
+
+ type = lp_type_float_vec(64);
+ bld->type = type;
+ vec_double_type = lp_build_vec_type(type);
+ res = LLVMBuildBitCast(bld->builder, res, vec_double_type, "");
+
+ return res;
+}
+
+static LLVMValueRef
+lp_cast_from_double_msb(struct lp_build_context *bld,
+ LLVMValueRef double_value)
+{
+ LLVMTypeRef double_type;
+ LLVMValueRef res;
+ struct lp_type type = lp_type_uint_vec(64);
+
+ double_type = lp_build_vec_type(type);
+ res = LLVMBuildBitCast(bld->builder, double_value, double_type, "");
+ res = LLVMBuildLShr(bld->builder, res, lp_build_const_int_vec(type, 32), "");
+ res = LLVMBuildBitCast(bld->builder, res, bld->vec_type, "");
+
+ return res;
+}
+
+
+static LLVMValueRef
+lp_cast_from_double_lsb(struct lp_build_context *bld,
+ LLVMValueRef double_value)
+{
+ LLVMTypeRef double_type;
+ LLVMValueRef res;
+ struct lp_type type = lp_type_uint_vec(64);
+
+ double_type = lp_build_vec_type(type);
+ res = LLVMBuildBitCast(bld->builder, double_value, double_type, "");
+ res = LLVMBuildAnd(bld->builder, res, lp_build_const_int_vec(type, 0x00000000FFFFFFFF), "");
+ res = LLVMBuildBitCast(bld->builder, res, bld->vec_type, "");
+
+ return res;
+}
/**
* Predicated fragment kill.
@@ -1982,6 +2044,37 @@ emit_instruction(
case TGSI_OPCODE_NOP:
break;
+ case TGSI_OPCODE_DMUL:
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X) && IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y)) {
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Y );
+
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_X );
+ tmp3 = emit_fetch( bld, inst, 1, CHAN_Y );
+
+ src0 = lp_cast_to_double(&bld->base, tmp0, tmp1);
+ src1 = lp_cast_to_double(&bld->base, tmp2, tmp3);
+ tmp4 = lp_build_mul(&bld->base, src0, src1);
+ dst0[CHAN_X] = lp_cast_from_double_msb(&bld->base, tmp4);
+ dst0[CHAN_Y] = lp_cast_from_double_lsb(&bld->base, tmp4);
+ }
+
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z) && IS_DST0_CHANNEL_ENABLED(inst, CHAN_W)) {
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_Z );
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_W );
+
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_Z );
+ tmp3 = emit_fetch( bld, inst, 1, CHAN_W );
+
+ src0 = lp_cast_to_double(&bld->base, tmp0, tmp1);
+ src1 = lp_cast_to_double(&bld->base, tmp2, tmp3);
+ tmp4 = lp_build_mul(&bld->base, src0, src1);
+ dst0[CHAN_Z] = lp_cast_from_double_msb(&bld->base, tmp4);
+ dst0[CHAN_W] = lp_cast_from_double_lsb(&bld->base, tmp4);
+
+ }
+ break;
+
default:
return FALSE;
}