#include "brw_context.h"
#include "brw_eu.h"
#include "intel_asm_annotation.h"
+#include "util/u_atomic.h" /* for p_atomic_cmpxchg */
static const uint32_t g45_control_index_table[32] = {
0b00000000000000000,
(brw_inst_bits(src, 34, 32) << 21) | /* 3b */
(brw_inst_bits(src, 28, 8)); /* 21b */
- if (brw->is_cherryview)
+ if (brw->gen >= 9 || 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++) {
(brw_inst_bits(src, 72, 65) << 19) | /* 8b */
(brw_inst_bits(src, 55, 37)); /* 19b */
- if (brw->is_cherryview) {
+ if (brw->gen >= 9 || brw->is_cherryview) {
uncompacted |=
(brw_inst_bits(src, 126, 125) << 47) | /* 2b */
(brw_inst_bits(src, 105, 104) << 45) | /* 2b */
return false;
}
+static bool
+has_unmapped_bits(struct brw_context *brw, brw_inst *src)
+{
+ /* Check for instruction bits that don't map to any of the fields of the
+ * compacted instruction. The instruction cannot be compacted if any of
+ * them are set. They overlap with:
+ * - NibCtrl (bit 47 on Gen7, bit 11 on Gen8)
+ * - Dst.AddrImm[9] (bit 47 on Gen8)
+ * - Src0.AddrImm[9] (bit 95 on Gen8)
+ * - Imm64[27:31] (bits 91-95 on Gen7, bit 95 on Gen8)
+ * - UIP[31] (bit 95 on Gen8)
+ */
+ if (brw->gen >= 8) {
+ assert(!brw_inst_bits(src, 7, 7));
+ return brw_inst_bits(src, 95, 95) ||
+ brw_inst_bits(src, 47, 47) ||
+ brw_inst_bits(src, 11, 11);
+ } else {
+ assert(!brw_inst_bits(src, 7, 7) &&
+ !(brw->gen < 7 && brw_inst_bits(src, 90, 90)));
+ return brw_inst_bits(src, 95, 91) ||
+ brw_inst_bits(src, 47, 47);
+ }
+}
+
+static bool
+has_3src_unmapped_bits(struct brw_context *brw, brw_inst *src)
+{
+ /* Check for three-source instruction bits that don't map to any of the
+ * fields of the compacted instruction. All of them seem to be reserved
+ * bits currently.
+ */
+ if (brw->gen >= 9 || brw->is_cherryview) {
+ assert(!brw_inst_bits(src, 127, 127) &&
+ !brw_inst_bits(src, 7, 7));
+ } else {
+ assert(brw->gen >= 8);
+ assert(!brw_inst_bits(src, 127, 126) &&
+ !brw_inst_bits(src, 105, 105) &&
+ !brw_inst_bits(src, 84, 84) &&
+ !brw_inst_bits(src, 36, 35) &&
+ !brw_inst_bits(src, 7, 7));
+ }
+
+ return false;
+}
+
static bool
brw_try_compact_3src_instruction(struct brw_context *brw, brw_compact_inst *dst,
brw_inst *src)
{
assert(brw->gen >= 8);
+ if (has_3src_unmapped_bits(brw, src))
+ return false;
+
#define compact(field) \
brw_compact_inst_set_3src_##field(dst, brw_inst_3src_##field(brw, src))
return false;
}
+ if (has_unmapped_bits(brw, src))
+ return false;
+
memset(&temp, 0, sizeof(temp));
brw_compact_inst_set_opcode(&temp, brw_inst_opcode(brw, src));
brw_inst_set_bits(dst, 34, 32, (uncompacted >> 21) & 0x7);
brw_inst_set_bits(dst, 28, 8, (uncompacted >> 0) & 0x1fffff);
- if (brw->is_cherryview)
+ if (brw->gen >= 9 || brw->is_cherryview)
brw_inst_set_bits(dst, 36, 35, (uncompacted >> 24) & 0x3);
}
brw_inst_set_bits(dst, 72, 65, (uncompacted >> 19) & 0xff);
brw_inst_set_bits(dst, 55, 37, (uncompacted >> 0) & 0x7ffff);
- if (brw->is_cherryview) {
+ if (brw->gen >= 9 || 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);
void
brw_init_compaction_tables(struct brw_context *brw)
{
+ static bool initialized;
+ if (initialized || p_atomic_cmpxchg(&initialized, false, true) != false)
+ return;
+
assert(g45_control_index_table[ARRAY_SIZE(g45_control_index_table) - 1] != 0);
assert(g45_datatype_table[ARRAY_SIZE(g45_datatype_table) - 1] != 0);
assert(g45_subreg_table[ARRAY_SIZE(g45_subreg_table) - 1] != 0);
assert(gen8_src_index_table[ARRAY_SIZE(gen8_src_index_table) - 1] != 0);
switch (brw->gen) {
+ case 9:
case 8:
control_index_table = gen8_control_index_table;
datatype_table = gen8_datatype_table;
*/
int old_ip[(p->next_insn_offset - start_offset) / sizeof(brw_compact_inst)];
- /* FIXME: Mark reported that SNB GT2 (GT1 appears fine) is hanging after
- * commit a36631b74.
- */
- if (brw->gen == 6)
- return;
-
if (brw->gen == 4 && !brw->is_g4x)
return;