diff options
author | James Benton <jbenton@vmware.com> | 2012-05-30 14:36:22 +0100 |
---|---|---|
committer | José Fonseca <jfonseca@vmware.com> | 2012-11-28 19:14:20 +0000 |
commit | cd548836a1410220090dbd7866735a7493c7cf47 (patch) | |
tree | 264c4083d4d495f22ced736ac5e6c5bca3b0700c /src/gallium/auxiliary/gallivm/lp_bld_arit.c | |
parent | c3a465ae98be6db1aee582f15380944b8faaeafc (diff) | |
download | external_mesa3d-cd548836a1410220090dbd7866735a7493c7cf47.zip external_mesa3d-cd548836a1410220090dbd7866735a7493c7cf47.tar.gz external_mesa3d-cd548836a1410220090dbd7866735a7493c7cf47.tar.bz2 |
gallivm: Add support for unorm16 in lp_build_mul.
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
Diffstat (limited to 'src/gallium/auxiliary/gallivm/lp_bld_arit.c')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_arit.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index d23ff0b..ca96a6b 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -691,6 +691,35 @@ lp_build_mul_u8n(struct gallivm_state *gallivm, return ab; } +/** + * Normalized 16bit multiplication. + * + * Utilises same principle as above code. + */ +static LLVMValueRef +lp_build_mul_u16n(struct gallivm_state *gallivm, + struct lp_type i32_type, + LLVMValueRef a, LLVMValueRef b) +{ + LLVMBuilderRef builder = gallivm->builder; + LLVMValueRef c16; + LLVMValueRef ab; + + assert(!i32_type.floating); + assert(lp_check_value(i32_type, a)); + assert(lp_check_value(i32_type, b)); + + c16 = lp_build_const_int_vec(gallivm, i32_type, 16); + + /* ab/65535 ~= (ab + (ab >> 16) + 0x8000) >> 16 */ + ab = LLVMBuildMul(builder, a, b, ""); + ab = LLVMBuildAdd(builder, ab, LLVMBuildLShr(builder, ab, c16, ""), ""); + ab = LLVMBuildAdd(builder, ab, lp_build_const_int_vec(gallivm, i32_type, 0x8000), ""); + + ab = LLVMBuildLShr(builder, ab, c16, ""); + + return ab; +} /** * Generate a * b @@ -736,6 +765,22 @@ lp_build_mul(struct lp_build_context *bld, return ab; } + if(type.width == 16) { + struct lp_type i32_type = lp_wider_type(type); + LLVMValueRef al, ah, bl, bh, abl, abh, ab; + + lp_build_unpack2(bld->gallivm, type, i32_type, a, &al, &ah); + lp_build_unpack2(bld->gallivm, type, i32_type, b, &bl, &bh); + + /* PMULLW, PSRLW, PADDW */ + abl = lp_build_mul_u16n(bld->gallivm, i32_type, al, bl); + abh = lp_build_mul_u16n(bld->gallivm, i32_type, ah, bh); + + ab = lp_build_pack2(bld->gallivm, i32_type, type, abl, abh); + + return ab; + } + /* FIXME */ assert(0); } |