i965: Add support for compacting 3-src instructions on Gen8.
authorMatt Turner <mattst88@gmail.com>
Sun, 15 Jun 2014 18:29:22 +0000 (11:29 -0700)
committerMatt Turner <mattst88@gmail.com>
Tue, 19 Aug 2014 01:18:50 +0000 (18:18 -0700)
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_eu_compact.c

index 2acf5d3..6b1cf12 100644 (file)
@@ -611,6 +611,97 @@ set_src1_index(struct brw_context *brw, brw_compact_inst *dst, brw_inst *src,
    return true;
 }
 
+static bool
+set_3src_control_index(struct brw_context *brw, brw_compact_inst *dst, brw_inst *src)
+{
+   assert(brw->gen >= 8);
+
+   uint32_t uncompacted =                  /* 24b/BDW; 26b/CHV */
+      (brw_inst_bits(src, 34, 32) << 21) | /*  3b */
+      (brw_inst_bits(src, 28,  8));        /* 21b */
+
+   if (brw->is_cherryview)
+      uncompacted |= brw_inst_bits(src, 36, 35) << 24; /* 2b */
+
+   for (int i = 0; i < ARRAY_SIZE(gen8_3src_control_index_table); i++) {
+      if (gen8_3src_control_index_table[i] == uncompacted) {
+         brw_compact_inst_set_3src_control_index(dst, i);
+        return true;
+      }
+   }
+
+   return false;
+}
+
+static bool
+set_3src_source_index(struct brw_context *brw, brw_compact_inst *dst, brw_inst *src)
+{
+   assert(brw->gen >= 8);
+
+   uint64_t uncompacted =                    /* 46b/BDW; 49b/CHV */
+      (brw_inst_bits(src,  83,  83) << 43) | /*  1b */
+      (brw_inst_bits(src, 114, 107) << 35) | /*  8b */
+      (brw_inst_bits(src,  93,  86) << 27) | /*  8b */
+      (brw_inst_bits(src,  72,  65) << 19) | /*  8b */
+      (brw_inst_bits(src,  55,  37));        /* 19b */
+
+   if (brw->is_cherryview) {
+      uncompacted |=
+         (brw_inst_bits(src, 126, 125) << 47) | /* 2b */
+         (brw_inst_bits(src, 105, 104) << 45) | /* 2b */
+         (brw_inst_bits(src,  84,  84) << 44);  /* 1b */
+   } else {
+      uncompacted |=
+         (brw_inst_bits(src, 125, 125) << 45) | /* 1b */
+         (brw_inst_bits(src, 104, 104) << 44);  /* 1b */
+   }
+
+   for (int i = 0; i < ARRAY_SIZE(gen8_3src_source_index_table); i++) {
+      if (gen8_3src_source_index_table[i] == uncompacted) {
+         brw_compact_inst_set_3src_source_index(dst, i);
+        return true;
+      }
+   }
+
+   return false;
+}
+
+static bool
+brw_try_compact_3src_instruction(struct brw_context *brw, brw_compact_inst *dst,
+                                 brw_inst *src)
+{
+   assert(brw->gen >= 8);
+
+#define compact(field) \
+   brw_compact_inst_set_3src_##field(dst, brw_inst_3src_##field(brw, src))
+
+   compact(opcode);
+
+   if (!set_3src_control_index(brw, dst, src))
+      return false;
+
+   if (!set_3src_source_index(brw, dst, src))
+      return false;
+
+   compact(dst_reg_nr);
+   compact(src0_rep_ctrl);
+   brw_compact_inst_set_3src_cmpt_control(dst, true);
+   compact(debug_control);
+   compact(saturate);
+   compact(src1_rep_ctrl);
+   compact(src2_rep_ctrl);
+   compact(src0_reg_nr);
+   compact(src1_reg_nr);
+   compact(src2_reg_nr);
+   compact(src0_subreg_nr);
+   compact(src1_subreg_nr);
+   compact(src2_subreg_nr);
+
+#undef compact
+
+   return true;
+}
+
 /* Compacted instructions have 12-bits for immediate sources, and a 13th bit
  * that's replicated through the high 20 bits.
  *
@@ -627,6 +718,13 @@ is_compactable_immediate(unsigned imm)
    return imm == 0 || imm == 0xfffff000;
 }
 
+/* Returns whether an opcode takes three sources. */
+static bool
+is_3src(uint32_t op)
+{
+   return opcode_descs[op].nsrc == 3;
+}
+
 /**
  * Tries to compact instruction src into dst.
  *
@@ -651,6 +749,16 @@ brw_try_compact_instruction(struct brw_context *brw, brw_compact_inst *dst,
       return false;
    }
 
+   if (brw->gen >= 8 && is_3src(brw_inst_opcode(brw, src))) {
+      memset(&temp, 0, sizeof(temp));
+      if (brw_try_compact_3src_instruction(brw, &temp, src)) {
+         *dst = temp;
+         return true;
+      } else {
+         return false;
+      }
+   }
+
    bool is_immediate =
       brw_inst_src0_reg_file(brw, src) == BRW_IMMEDIATE_VALUE ||
       brw_inst_src1_reg_file(brw, src) == BRW_IMMEDIATE_VALUE;
@@ -767,12 +875,89 @@ set_uncompacted_src1(struct brw_context *brw, brw_inst *dst,
    }
 }
 
+static void
+set_uncompacted_3src_control_index(struct brw_context *brw, brw_inst *dst,
+                                   brw_compact_inst *src)
+{
+   assert(brw->gen >= 8);
+
+   uint32_t compacted = brw_compact_inst_3src_control_index(src);
+   uint32_t uncompacted = gen8_3src_control_index_table[compacted];
+
+   brw_inst_set_bits(dst, 34, 32, (uncompacted >> 21) & 0x7);
+   brw_inst_set_bits(dst, 28,  8, (uncompacted >>  0) & 0x1fffff);
+
+   if (brw->is_cherryview)
+      brw_inst_set_bits(dst, 36, 35, (uncompacted >> 24) & 0x3);
+}
+
+static void
+set_uncompacted_3src_source_index(struct brw_context *brw, brw_inst *dst,
+                                  brw_compact_inst *src)
+{
+   assert(brw->gen >= 8);
+
+   uint32_t compacted = brw_compact_inst_3src_source_index(src);
+   uint64_t uncompacted = gen8_3src_source_index_table[compacted];
+
+   brw_inst_set_bits(dst,  83,  83, (uncompacted >> 43) & 0x1);
+   brw_inst_set_bits(dst, 114, 107, (uncompacted >> 35) & 0xff);
+   brw_inst_set_bits(dst,  93,  86, (uncompacted >> 27) & 0xff);
+   brw_inst_set_bits(dst,  72,  65, (uncompacted >> 19) & 0xff);
+   brw_inst_set_bits(dst,  55,  37, (uncompacted >>  0) & 0x7ffff);
+
+   if (brw->is_cherryview) {
+      brw_inst_set_bits(dst, 126, 125, (uncompacted >> 47) & 0x3);
+      brw_inst_set_bits(dst, 105, 104, (uncompacted >> 45) & 0x3);
+      brw_inst_set_bits(dst,  84,  84, (uncompacted >> 44) & 0x1);
+   } else {
+      brw_inst_set_bits(dst, 125, 125, (uncompacted >> 45) & 0x1);
+      brw_inst_set_bits(dst, 104, 104, (uncompacted >> 44) & 0x1);
+   }
+}
+
+static void
+brw_uncompact_3src_instruction(struct brw_context *brw, brw_inst *dst,
+                               brw_compact_inst *src)
+{
+   assert(brw->gen >= 8);
+
+#define uncompact(field) \
+   brw_inst_set_3src_##field(brw, dst, brw_compact_inst_3src_##field(src))
+
+   uncompact(opcode);
+
+   set_uncompacted_3src_control_index(brw, dst, src);
+   set_uncompacted_3src_source_index(brw, dst, src);
+
+   uncompact(dst_reg_nr);
+   uncompact(src0_rep_ctrl);
+   brw_inst_set_3src_cmpt_control(brw, dst, false);
+   uncompact(debug_control);
+   uncompact(saturate);
+   uncompact(src1_rep_ctrl);
+   uncompact(src2_rep_ctrl);
+   uncompact(src0_reg_nr);
+   uncompact(src1_reg_nr);
+   uncompact(src2_reg_nr);
+   uncompact(src0_subreg_nr);
+   uncompact(src1_subreg_nr);
+   uncompact(src2_subreg_nr);
+
+#undef uncompact
+}
+
 void
 brw_uncompact_instruction(struct brw_context *brw, brw_inst *dst,
                           brw_compact_inst *src)
 {
    memset(dst, 0, sizeof(*dst));
 
+   if (brw->gen >= 8 && is_3src(brw_compact_inst_3src_opcode(src))) {
+      brw_uncompact_3src_instruction(brw, dst, src);
+      return;
+   }
+
    brw_inst_set_opcode(brw, dst, brw_compact_inst_opcode(src));
    brw_inst_set_debug_control(brw, dst, brw_compact_inst_debug_control(src));