From 3f78f719732b87e6707f94c187ad6e263c6c2ef0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 15 Aug 2011 22:36:18 -0700 Subject: [PATCH] i965/fs: Fix 32-bit integer multiplication. The MUL opcode does a 16bit * 32bit multiply, and we need to do the MACH to get the top 16bit * 32bit added in. Fixes fs-op-mult-int-*, fs-op-mult-ivec* Reviewed-by: Kenneth Graunke --- src/mesa/drivers/dri/i965/brw_fs_emit.cpp | 5 +++++ src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/i965/brw_fs_emit.cpp b/src/mesa/drivers/dri/i965/brw_fs_emit.cpp index 7367cca..482d250 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_emit.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_emit.cpp @@ -630,6 +630,11 @@ fs_visitor::generate_code() case BRW_OPCODE_MUL: brw_MUL(p, dst, src[0], src[1]); break; + case BRW_OPCODE_MACH: + brw_set_acc_write_control(p, 1); + brw_MACH(p, dst, src[0], src[1]); + brw_set_acc_write_control(p, 0); + break; case BRW_OPCODE_FRC: brw_FRC(p, dst, src[0]); diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 8b4f5bb..2dc9132 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -287,7 +287,23 @@ fs_visitor::visit(ir_expression *ir) break; case ir_binop_mul: - emit(BRW_OPCODE_MUL, this->result, op[0], op[1]); + if (ir->type->is_integer()) { + /* For integer multiplication, the MUL uses the low 16 bits + * of one of the operands (src0 on gen6, src1 on gen7). The + * MACH accumulates in the contribution of the upper 16 bits + * of that operand. + * + * FINISHME: Emit just the MUL if we know an operand is small + * enough. + */ + struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_D); + + emit(BRW_OPCODE_MUL, acc, op[0], op[1]); + emit(BRW_OPCODE_MACH, reg_null_d, op[0], op[1]); + emit(BRW_OPCODE_MOV, this->result, fs_reg(acc)); + } else { + emit(BRW_OPCODE_MUL, this->result, op[0], op[1]); + } break; case ir_binop_div: assert(!"not reached: should be handled by ir_div_to_mul_rcp"); -- 2.7.4