i965/fs: Fix 32-bit integer multiplication.
authorEric Anholt <eric@anholt.net>
Tue, 16 Aug 2011 05:36:18 +0000 (22:36 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 17 Aug 2011 18:51:01 +0000 (11:51 -0700)
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 <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_fs_emit.cpp
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp

index 7367ccaa7e076c691f0a22ebc57fb454c5aa8f8b..482d250c333bce06928880ab35291a1359242c68 100644 (file)
@@ -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]);
index 8b4f5bbac15a707b4519cb9995e22618a90a0267..2dc9132cec69a6021d04233bbb10617ebb9b0c46 100644 (file)
@@ -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");