diff options
author | Zack Rusin <[email protected]> | 2013-10-08 15:11:02 -0400 |
---|---|---|
committer | Zack Rusin <[email protected]> | 2013-10-09 18:30:20 -0400 |
commit | 6905698fc21710c18722295dedceb96ef5d5923b (patch) | |
tree | 448459df4604df868382f02fac033f354356f1c0 /src/gallium/auxiliary | |
parent | c01c6a95b41607dc58a343b2aa67bc3da673ca35 (diff) |
gallium: Add support for 32x32 muls with 64 bit results
The code introduces two new 32bit integer multiplication opcodes which
can be used to produce correct 64 bit results. GLSL, OpenCL and D3D10+
require them. We use two seperate opcodes, because they match the
behavior of GLSL and OpenCL, are a lot easier to add than a single
opcode with multiple destinations and because there's not much (any)
difference wrt code-generation.
Signed-off-by: Zack Rusin <[email protected]>
Reviewed-by: José Fonseca <[email protected]>
Reviewed-by: Roland Scheidegger <[email protected]>
Reviewed-by: Brian Paul <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r-- | src/gallium/auxiliary/tgsi/tgsi_exec.c | 34 | ||||
-rw-r--r-- | src/gallium/auxiliary/tgsi/tgsi_info.c | 6 | ||||
-rw-r--r-- | src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h | 3 | ||||
-rw-r--r-- | src/gallium/auxiliary/tgsi/tgsi_util.c | 2 |
4 files changed, 45 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 0750a502f16..6db1238a60d 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -3478,6 +3478,32 @@ micro_umul(union tgsi_exec_channel *dst, } static void +micro_imul_hi(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ +#define I64M(x, y) ((((int64_t)x) * ((int64_t)y)) >> 32) + dst->i[0] = I64M(src0->i[0], src1->i[0]); + dst->i[1] = I64M(src0->i[1], src1->i[1]); + dst->i[2] = I64M(src0->i[2], src1->i[2]); + dst->i[3] = I64M(src0->i[3], src1->i[3]); +#undef I64M +} + +static void +micro_umul_hi(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ +#define U64M(x, y) ((((uint64_t)x) * ((uint64_t)y)) >> 32) + dst->u[0] = U64M(src0->u[0], src1->u[0]); + dst->u[1] = U64M(src0->u[1], src1->u[1]); + dst->u[2] = U64M(src0->u[2], src1->u[2]); + dst->u[3] = U64M(src0->u[3], src1->u[3]); +#undef U64M +} + +static void micro_useq(union tgsi_exec_channel *dst, const union tgsi_exec_channel *src0, const union tgsi_exec_channel *src1) @@ -4277,6 +4303,14 @@ exec_instruction( exec_vector_binary(mach, inst, micro_umul, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); break; + case TGSI_OPCODE_IMUL_HI: + exec_vector_binary(mach, inst, micro_imul_hi, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_UMUL_HI: + exec_vector_binary(mach, inst, micro_umul_hi, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + case TGSI_OPCODE_USEQ: exec_vector_binary(mach, inst, micro_useq, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); break; diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c index 7a5d18f59c5..0beef44454d 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.c +++ b/src/gallium/auxiliary/tgsi/tgsi_info.c @@ -219,6 +219,8 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] = { 1, 3, 1, 0, 0, 0, OTHR, "TEX2", TGSI_OPCODE_TEX2 }, { 1, 3, 1, 0, 0, 0, OTHR, "TXB2", TGSI_OPCODE_TXB2 }, { 1, 3, 1, 0, 0, 0, OTHR, "TXL2", TGSI_OPCODE_TXL2 }, + { 1, 2, 0, 0, 0, 0, COMP, "IMUL_HI", TGSI_OPCODE_IMUL_HI }, + { 1, 2, 0, 0, 0, 0, COMP, "UMUL_HI", TGSI_OPCODE_UMUL_HI }, }; const struct tgsi_opcode_info * @@ -297,6 +299,7 @@ tgsi_opcode_infer_type( uint opcode ) case TGSI_OPCODE_USLT: case TGSI_OPCODE_USNE: case TGSI_OPCODE_SVIEWINFO: + case TGSI_OPCODE_UMUL_HI: return TGSI_TYPE_UNSIGNED; case TGSI_OPCODE_ARL: case TGSI_OPCODE_ARR: @@ -317,6 +320,7 @@ tgsi_opcode_infer_type( uint opcode ) case TGSI_OPCODE_UARL: case TGSI_OPCODE_IABS: case TGSI_OPCODE_ISSG: + case TGSI_OPCODE_IMUL_HI: return TGSI_TYPE_SIGNED; default: return TGSI_TYPE_FLOAT; @@ -339,7 +343,9 @@ tgsi_opcode_infer_src_type( uint opcode ) case TGSI_OPCODE_CASE: case TGSI_OPCODE_SAMPLE_I: case TGSI_OPCODE_SAMPLE_I_MS: + case TGSI_OPCODE_UMUL_HI: return TGSI_TYPE_UNSIGNED; + case TGSI_OPCODE_IMUL_HI: case TGSI_OPCODE_I2F: return TGSI_TYPE_SIGNED; case TGSI_OPCODE_ARL: diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h index b8144a8916b..1ef78ddcc8f 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h +++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h @@ -204,6 +204,9 @@ OP12(SAMPLE_INFO) OP13(UCMP) +OP12(IMUL_HI) +OP12(UMUL_HI) + #undef OP00 #undef OP01 #undef OP10 diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.c b/src/gallium/auxiliary/tgsi/tgsi_util.c index b3bc8f283a4..73a0667fd06 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_util.c +++ b/src/gallium/auxiliary/tgsi/tgsi_util.c @@ -243,6 +243,8 @@ tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst, case TGSI_OPCODE_USHR: case TGSI_OPCODE_USLT: case TGSI_OPCODE_USNE: + case TGSI_OPCODE_IMUL_HI: + case TGSI_OPCODE_UMUL_HI: /* Channel-wise operations */ read_mask = write_mask; break; |