diff options
author | Igor Oliveira <igor.oliveira@openbossa.org> | 2010-09-28 15:30:27 -0400 |
---|---|---|
committer | Igor Oliveira <igor.oliveira@openbossa.org> | 2010-09-29 23:07:26 -0400 |
commit | 964e23044eb741cbe6f2a6fd888a0fe37fc6052d (patch) | |
tree | 1df74895749a0b91dd15523917d53eae443e1054 | |
parent | 081d0529b4cabf22229030052d422af0bff2c82b (diff) |
llvmpipe: add initial support to double opcodes in llvmpipe.
- implement DMUL opcode
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 93 |
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; } |