ilo: EOL drop unmaintained gallium drv from buildsys
[mesa.git] / src / gallium / drivers / ilo / shader / toy_compiler_disasm.c
index f70b93d7ccf4a6844107b0d289b8130b04ed9f00..576cd2b3b2261fb1991fea3417f55597b2e4925b 100644 (file)
@@ -39,7 +39,7 @@ struct disasm_printer {
 
 struct disasm_operand {
    unsigned file:2;
-   unsigned type:3;
+   unsigned type:4;
 
    unsigned addr_mode:1;
    unsigned reg:8;
@@ -70,7 +70,7 @@ struct disasm_src_operand {
 };
 
 struct disasm_inst {
-   const struct ilo_dev_info *dev;
+   const struct ilo_dev *dev;
 
    unsigned has_jip:1;
    unsigned has_uip:1;
@@ -90,6 +90,8 @@ struct disasm_inst {
    unsigned fc:4;
 
    unsigned acc_wr_ctrl:1;
+   unsigned branch_ctrl:1;
+
    unsigned cmpt_ctrl:1;
    unsigned debug_ctrl:1;
    unsigned saturate:1;
@@ -104,7 +106,23 @@ struct disasm_inst {
    struct disasm_src_operand src1;
    union {
       struct disasm_src_operand src2;
-      uint32_t imm32;
+      uint64_t imm64;
+
+      uint32_t ud;
+      int32_t d;
+      uint16_t uw;
+      int16_t w;
+      float f;
+
+      struct {
+         int16_t jip;
+         int16_t uip;
+      } ip16;
+
+      struct {
+         int32_t jip;
+         int32_t uip;
+      } ip32;
    } u;
 };
 
@@ -147,6 +165,7 @@ static const struct {
    [GEN75_OPCODE_CALLA]      = { "calla",    1 },
    [GEN6_OPCODE_CALL]        = { "call",     1 },
    [GEN6_OPCODE_RETURN]      = { "return",   1 },
+   [GEN8_OPCODE_GOTO]        = { "goto",     1 },
    [GEN6_OPCODE_WAIT]        = { "wait",     1 },
    [GEN6_OPCODE_SEND]        = { "send",     1 },
    [GEN6_OPCODE_SENDC]       = { "sendc",    1 },
@@ -181,8 +200,10 @@ static const struct {
 };
 
 static void
-disasm_inst_decode_dw0_gen6(struct disasm_inst *inst, uint32_t dw0)
+disasm_inst_decode_dw0_opcode_gen6(struct disasm_inst *inst, uint32_t dw0)
 {
+   ILO_DEV_ASSERT(inst->dev, 6, 8);
+
    inst->opcode = GEN_EXTRACT(dw0, GEN6_INST_OPCODE);
 
    switch (inst->opcode) {
@@ -190,6 +211,10 @@ disasm_inst_decode_dw0_gen6(struct disasm_inst *inst, uint32_t dw0)
       inst->has_jip = true;
       inst->has_uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(7));
       break;
+   case GEN6_OPCODE_ELSE:
+      inst->has_jip = true;
+      inst->has_uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8));
+      break;
    case GEN6_OPCODE_BREAK:
    case GEN6_OPCODE_CONT:
    case GEN6_OPCODE_HALT:
@@ -198,7 +223,6 @@ disasm_inst_decode_dw0_gen6(struct disasm_inst *inst, uint32_t dw0)
    case GEN6_OPCODE_JMPI:
    case GEN7_OPCODE_BRD:
    case GEN7_OPCODE_BRC:
-   case GEN6_OPCODE_ELSE:
    case GEN6_OPCODE_ENDIF:
    case GEN6_OPCODE_CASE:
    case GEN6_OPCODE_WHILE:
@@ -210,10 +234,25 @@ disasm_inst_decode_dw0_gen6(struct disasm_inst *inst, uint32_t dw0)
    default:
       break;
    }
+}
+
+static void
+disasm_inst_decode_dw0_gen6(struct disasm_inst *inst, uint32_t dw0)
+{
+   ILO_DEV_ASSERT(inst->dev, 6, 8);
+
+   disasm_inst_decode_dw0_opcode_gen6(inst, dw0);
 
    inst->access_mode = GEN_EXTRACT(dw0, GEN6_INST_ACCESSMODE);
-   inst->mask_ctrl = GEN_EXTRACT(dw0, GEN6_INST_MASKCTRL);
-   inst->dep_ctrl = GEN_EXTRACT(dw0, GEN6_INST_DEPCTRL);
+
+   if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
+      inst->dep_ctrl = GEN_EXTRACT(dw0, GEN8_INST_DEPCTRL);
+      inst->nib_ctrl = (bool) (dw0 & GEN8_INST_NIBCTRL);
+   } else {
+      inst->mask_ctrl = GEN_EXTRACT(dw0, GEN6_INST_MASKCTRL);
+      inst->dep_ctrl = GEN_EXTRACT(dw0, GEN6_INST_DEPCTRL);
+   }
+
    inst->qtr_ctrl = GEN_EXTRACT(dw0, GEN6_INST_QTRCTRL);
    inst->thread_ctrl = GEN_EXTRACT(dw0, GEN6_INST_THREADCTRL);
    inst->pred_ctrl = GEN_EXTRACT(dw0, GEN6_INST_PREDCTRL);
@@ -235,22 +274,29 @@ disasm_inst_decode_dw0_gen6(struct disasm_inst *inst, uint32_t dw0)
       break;
    }
 
-   inst->acc_wr_ctrl = (bool) (dw0 & GEN6_INST_ACCWRCTRL);
+   switch (inst->opcode) {
+   case GEN6_OPCODE_IF:
+   case GEN6_OPCODE_ELSE:
+   case GEN8_OPCODE_GOTO:
+      if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
+         inst->branch_ctrl = (bool) (dw0 & GEN8_INST_BRANCHCTRL);
+         break;
+      }
+   default:
+      inst->acc_wr_ctrl = (bool) (dw0 & GEN6_INST_ACCWRCTRL);
+      break;
+   }
+
    inst->cmpt_ctrl = (bool) (dw0 & GEN6_INST_CMPTCTRL);
    inst->debug_ctrl = (bool) (dw0 & GEN6_INST_DEBUGCTRL);
    inst->saturate = (bool) (dw0 & GEN6_INST_SATURATE);
 }
 
-static bool
-disasm_inst_jip_in_dw1_high_gen6(const struct disasm_inst *inst)
-{
-   return (ilo_dev_gen(inst->dev) == ILO_GEN(6) &&
-           inst->has_jip && !inst->has_uip);
-}
-
 static void
-disasm_inst_decode_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
+disasm_inst_decode_dw1_low_gen6(struct disasm_inst *inst, uint32_t dw1)
 {
+   ILO_DEV_ASSERT(inst->dev, 6, 7.5);
+
    inst->dst.base.file = GEN_EXTRACT(dw1, GEN6_INST_DST_FILE);
    inst->dst.base.type = GEN_EXTRACT(dw1, GEN6_INST_DST_TYPE);
    inst->src0.base.file = GEN_EXTRACT(dw1, GEN6_INST_SRC0_FILE);
@@ -260,11 +306,30 @@ disasm_inst_decode_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
 
    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
       inst->nib_ctrl = (bool) (dw1 & GEN7_INST_NIBCTRL);
+}
 
-   if (disasm_inst_jip_in_dw1_high_gen6(inst)) {
-      inst->u.imm32 = dw1 >> 16;
-      return;
-   }
+static void
+disasm_inst_decode_dw1_low_gen8(struct disasm_inst *inst, uint32_t dw1)
+{
+   ILO_DEV_ASSERT(inst->dev, 8, 8);
+
+   inst->flag_subreg = GEN_EXTRACT(dw1, GEN8_INST_FLAG_SUBREG);
+   inst->flag_reg = GEN_EXTRACT(dw1, GEN8_INST_FLAG_REG);
+   inst->mask_ctrl = GEN_EXTRACT(dw1, GEN8_INST_MASKCTRL);
+
+   inst->dst.base.file = GEN_EXTRACT(dw1, GEN8_INST_DST_FILE);
+   inst->dst.base.type = GEN_EXTRACT(dw1, GEN8_INST_DST_TYPE);
+   inst->src0.base.file = GEN_EXTRACT(dw1, GEN8_INST_SRC0_FILE);
+   inst->src0.base.type = GEN_EXTRACT(dw1, GEN8_INST_SRC0_TYPE);
+
+   inst->dst.base.addr_imm = GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM_BIT9) <<
+      GEN8_INST_DST_ADDR_IMM_BIT9__SHR;
+}
+
+static void
+disasm_inst_decode_dw1_high_gen6(struct disasm_inst *inst, uint32_t dw1)
+{
+   ILO_DEV_ASSERT(inst->dev, 6, 8);
 
    inst->dst.base.addr_mode = GEN_EXTRACT(dw1, GEN6_INST_DST_ADDRMODE);
 
@@ -279,14 +344,31 @@ disasm_inst_decode_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
             GEN6_INST_DST_SUBREG_ALIGN16__SHR;
       }
    } else {
-      inst->dst.base.addr_subreg = GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_SUBREG);
+      if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
+         inst->dst.base.addr_subreg =
+            GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_SUBREG);
 
-      if (inst->access_mode == GEN6_ALIGN_1) {
-         inst->dst.base.addr_imm = GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_IMM);
+         /* bit 9 is already set in disasm_inst_decode_dw1_low_gen8() */
+         if (inst->access_mode == GEN6_ALIGN_1) {
+            inst->dst.base.addr_imm |=
+               GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM);
+         } else {
+            inst->dst.base.addr_imm |=
+               GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM_ALIGN16) <<
+               GEN8_INST_DST_ADDR_IMM_ALIGN16__SHR;
+         }
       } else {
-         inst->dst.base.addr_imm = GEN_EXTRACT(dw1,
-               GEN6_INST_DST_ADDR_IMM_ALIGN16) <<
-            GEN6_INST_DST_ADDR_IMM_ALIGN16__SHR;
+         inst->dst.base.addr_subreg =
+            GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_SUBREG);
+
+         if (inst->access_mode == GEN6_ALIGN_1) {
+            inst->dst.base.addr_imm =
+               GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_IMM);
+         } else {
+            inst->dst.base.addr_imm =
+               GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_IMM_ALIGN16) <<
+               GEN6_INST_DST_ADDR_IMM_ALIGN16__SHR;
+         }
       }
    }
 
@@ -298,24 +380,67 @@ disasm_inst_decode_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
       inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_INST_DST_WRITEMASK);
 }
 
+static void
+disasm_inst_decode_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
+{
+   ILO_DEV_ASSERT(inst->dev, 6, 8);
+
+   if (ilo_dev_gen(inst->dev) >= ILO_GEN(8))
+      disasm_inst_decode_dw1_low_gen8(inst, dw1);
+   else
+      disasm_inst_decode_dw1_low_gen6(inst, dw1);
+
+   if (ilo_dev_gen(inst->dev) == ILO_GEN(6) &&
+       inst->has_jip && !inst->has_uip)
+      inst->u.imm64 = dw1 >> 16;
+   else
+      disasm_inst_decode_dw1_high_gen6(inst, dw1);
+}
+
 static void
 disasm_inst_decode_dw2_dw3_gen6(struct disasm_inst *inst,
                                 uint32_t dw2, uint32_t dw3)
 {
-   int count, i;
+   int imm_bits = 0, count, i;
 
-   if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
-      inst->flag_reg = GEN_EXTRACT(dw2, GEN7_INST_FLAG_REG);
+   ILO_DEV_ASSERT(inst->dev, 6, 8);
 
-   inst->flag_subreg = GEN_EXTRACT(dw2, GEN6_INST_FLAG_SUBREG);
+   if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
+      /* how about real 64-bit immediates? */
+      if (inst->has_uip) {
+         imm_bits = 64;
+         inst->src1.base.file = GEN6_FILE_IMM;
+         inst->src1.base.type = GEN6_TYPE_D;
+      } else {
+         inst->src1.base.file = GEN_EXTRACT(dw2, GEN8_INST_SRC1_FILE);
+         inst->src1.base.type = GEN_EXTRACT(dw2, GEN8_INST_SRC1_TYPE);
 
-   if (inst->src0.base.file == GEN6_FILE_IMM ||
-       inst->src1.base.file == GEN6_FILE_IMM) {
-      count = 1;
-      if (!disasm_inst_jip_in_dw1_high_gen6(inst))
-         inst->u.imm32 = dw3;
+         if (inst->src0.base.file == GEN6_FILE_IMM ||
+             inst->src1.base.file == GEN6_FILE_IMM)
+            imm_bits = 32;
+      }
    } else {
+      if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
+         inst->flag_reg = GEN_EXTRACT(dw2, GEN7_INST_FLAG_REG);
+      inst->flag_subreg = GEN_EXTRACT(dw2, GEN6_INST_FLAG_SUBREG);
+
+      if (inst->src0.base.file == GEN6_FILE_IMM ||
+          inst->src1.base.file == GEN6_FILE_IMM)
+         imm_bits = 32;
+   }
+
+   switch (imm_bits) {
+   case 32:
+      inst->u.imm64 = dw3;
+      count = 1;
+      break;
+   case 64:
+      inst->u.imm64 = (uint64_t) dw2 << 32 | dw3;
+      count = 0;
+      break;
+   default:
       count = 2;
+      break;
    }
 
    for (i = 0; i < count; i++) {
@@ -334,14 +459,38 @@ disasm_inst_decode_dw2_dw3_gen6(struct disasm_inst *inst,
                GEN6_INST_SRC_SUBREG_ALIGN16__SHR;
          }
       } else {
-         src->base.addr_subreg = GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_SUBREG);
-
-         if (inst->access_mode == GEN6_ALIGN_1) {
-            src->base.addr_imm = GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM);
+         if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
+            src->base.addr_subreg =
+               GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_SUBREG);
+
+            if (inst->access_mode == GEN6_ALIGN_1) {
+               src->base.addr_imm = GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_IMM);
+            } else {
+               src->base.addr_imm =
+                  GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_IMM_ALIGN16) <<
+                  GEN8_INST_SRC_ADDR_IMM_ALIGN16__SHR;
+            }
+
+            if (i == 0) {
+               inst->dst.base.addr_imm |= GEN_EXTRACT(dw,
+                     GEN8_INST_SRC0_ADDR_IMM_BIT9) <<
+                  GEN8_INST_SRC0_ADDR_IMM_BIT9__SHR;
+            } else {
+               inst->dst.base.addr_imm |= GEN_EXTRACT(dw,
+                     GEN8_INST_SRC1_ADDR_IMM_BIT9) <<
+                  GEN8_INST_SRC1_ADDR_IMM_BIT9__SHR;
+            }
          } else {
-            src->base.addr_imm =
-               GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM_ALIGN16) <<
-               GEN6_INST_SRC_ADDR_IMM_ALIGN16__SHR;
+            src->base.addr_subreg =
+               GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_SUBREG);
+
+            if (inst->access_mode == GEN6_ALIGN_1) {
+               src->base.addr_imm = GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM);
+            } else {
+               src->base.addr_imm =
+                  GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM_ALIGN16) <<
+                  GEN6_INST_SRC_ADDR_IMM_ALIGN16__SHR;
+            }
          }
       }
 
@@ -373,13 +522,15 @@ disasm_inst_decode_dw2_dw3_gen6(struct disasm_inst *inst,
 static void
 disasm_inst_decode_3src_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
 {
-   static unsigned type_mapping[4] = {
+   static const unsigned type_mapping[4] = {
       [GEN7_TYPE_F_3SRC]   = GEN6_TYPE_F,
       [GEN7_TYPE_D_3SRC]   = GEN6_TYPE_D,
       [GEN7_TYPE_UD_3SRC]  = GEN6_TYPE_UD,
       [GEN7_TYPE_DF_3SRC]  = GEN7_TYPE_DF,
    };
 
+   ILO_DEV_ASSERT(inst->dev, 6, 7.5);
+
    inst->flag_subreg = GEN_EXTRACT(dw1, GEN6_3SRC_FLAG_SUBREG);
 
    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
@@ -424,6 +575,55 @@ disasm_inst_decode_3src_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
    inst->u.src2.absolute = (bool) (dw1 & GEN6_3SRC_SRC2_ABSOLUTE);
 }
 
+static void
+disasm_inst_decode_3src_dw1_gen8(struct disasm_inst *inst, uint32_t dw1)
+{
+   static const unsigned type_mapping[8] = {
+      [GEN7_TYPE_F_3SRC]   = GEN6_TYPE_F,
+      [GEN7_TYPE_D_3SRC]   = GEN6_TYPE_D,
+      [GEN7_TYPE_UD_3SRC]  = GEN6_TYPE_UD,
+      [GEN7_TYPE_DF_3SRC]  = GEN7_TYPE_DF,
+      /* map unknown types to unknown types */
+      [0x4]                = 0xf,
+      [0x5]                = 0xf,
+      [0x6]                = 0xf,
+      [0x7]                = 0xf,
+   };
+
+   ILO_DEV_ASSERT(inst->dev, 8, 8);
+
+   inst->flag_subreg = GEN_EXTRACT(dw1, GEN8_3SRC_FLAG_SUBREG);
+   inst->flag_reg = GEN_EXTRACT(dw1, GEN8_3SRC_FLAG_REG);
+   inst->mask_ctrl = GEN_EXTRACT(dw1, GEN8_3SRC_MASKCTRL);
+   inst->src0.absolute = (bool) (dw1 & GEN8_3SRC_SRC0_ABSOLUTE);
+   inst->src0.negate = (bool) (dw1 & GEN8_3SRC_SRC0_NEGATE);
+   inst->src1.negate = (bool) (dw1 & GEN8_3SRC_SRC1_NEGATE);
+   inst->src1.absolute = (bool) (dw1 & GEN8_3SRC_SRC1_ABSOLUTE);
+   inst->u.src2.negate = (bool) (dw1 & GEN8_3SRC_SRC2_NEGATE);
+   inst->u.src2.absolute = (bool) (dw1 & GEN8_3SRC_SRC2_ABSOLUTE);
+
+   inst->src0.base.file = GEN6_FILE_GRF;
+   inst->src0.base.type = GEN_EXTRACT(dw1, GEN8_3SRC_SRC_TYPE);
+   inst->src0.base.type = type_mapping[inst->src0.base.type];
+
+   inst->src1.base.file = GEN6_FILE_GRF;
+   inst->src1.base.type = inst->src0.base.type;
+
+   inst->u.src2.base.file = GEN6_FILE_GRF;
+   inst->u.src2.base.type = inst->src0.base.type;
+
+   inst->dst.base.file = GEN6_FILE_GRF;
+   inst->dst.base.type = GEN_EXTRACT(dw1, GEN8_3SRC_DST_TYPE);
+   inst->dst.base.type = type_mapping[inst->dst.base.type];
+   inst->dst.base.addr_mode = GEN6_ADDRMODE_DIRECT;
+   inst->dst.horz_stride = GEN6_HORZSTRIDE_1;
+
+   inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_3SRC_DST_WRITEMASK);
+   inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_SUBREG) <<
+      GEN6_3SRC_DST_SUBREG__SHR;
+   inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_REG);
+}
+
 static void
 disasm_inst_decode_3src_dw2_dw3_gen6(struct disasm_inst *inst,
                                      uint32_t dw2, uint32_t dw3)
@@ -431,6 +631,8 @@ disasm_inst_decode_3src_dw2_dw3_gen6(struct disasm_inst *inst,
    const uint64_t qw = (uint64_t) dw3 << 32 | dw2;
    int i;
 
+   ILO_DEV_ASSERT(inst->dev, 6, 8);
+
    for (i = 0; i < 3; i++) {
       struct disasm_src_operand *src = (i == 0) ? &inst->src0 :
                                        (i == 1) ? &inst->src1 :
@@ -499,7 +701,10 @@ disasm_inst_decode(struct disasm_inst *inst,
    disasm_inst_decode_dw0_gen6(inst, dw[0]);
 
    if (disasm_opcode_table[inst->opcode].src_count == 3) {
-      disasm_inst_decode_3src_dw1_gen6(inst, dw[1]);
+      if (ilo_dev_gen(inst->dev) >= ILO_GEN(8))
+         disasm_inst_decode_3src_dw1_gen8(inst, dw[1]);
+      else
+         disasm_inst_decode_3src_dw1_gen6(inst, dw[1]);
       disasm_inst_decode_3src_dw2_dw3_gen6(inst, dw[2], dw[3]);
    } else {
       disasm_inst_decode_dw1_gen6(inst, dw[1]);
@@ -584,6 +789,8 @@ disasm_inst_fc(const struct disasm_inst *inst)
    case GEN6_MATH_INT_DIV:             return "int_div";
    case GEN6_MATH_INT_DIV_QUOTIENT:    return "int_div_quotient";
    case GEN6_MATH_INT_DIV_REMAINDER:   return "int_div_remainder";
+   case GEN8_MATH_INVM:                return "invm";
+   case GEN8_MATH_RSQRTM:              return "rsqrtm";
    default:                            return "BAD";
    }
 }
@@ -736,9 +943,11 @@ disasm_inst_cmpt_ctrl(const struct disasm_inst *inst)
 static const char *
 disasm_inst_eot(const struct disasm_inst *inst)
 {
+   const uint32_t mdesc = inst->u.ud;
+
    if (inst->opcode == GEN6_OPCODE_SEND ||
        inst->opcode == GEN6_OPCODE_SENDC)
-      return (inst->u.imm32 & GEN6_MSG_EOT) ? " EOT" : "";
+      return (mdesc & GEN6_MSG_EOT) ? " EOT" : "";
    else
       return "";
 }
@@ -785,6 +994,8 @@ disasm_inst_type(const struct disasm_inst *inst,
       case GEN6_TYPE_VF_IMM:  return "VF";
       case GEN6_TYPE_V_IMM:   return "V";
       case GEN6_TYPE_F:       return "F";
+      case GEN8_TYPE_DF_IMM:  return "DF";
+      case GEN8_TYPE_HF_IMM:  return "HF";
       default:                return "BAD";
       }
    } else {
@@ -797,6 +1008,9 @@ disasm_inst_type(const struct disasm_inst *inst,
       case GEN6_TYPE_B:       return "B";
       case GEN7_TYPE_DF:      return "DF";
       case GEN6_TYPE_F:       return "F";
+      case GEN8_TYPE_UQ:      return "UQ";
+      case GEN8_TYPE_Q:       return "Q";
+      case GEN8_TYPE_HF:      return "HF";
       default:                return "BAD";
       }
    }
@@ -870,6 +1084,19 @@ disasm_inst_writemask(const struct disasm_inst *inst, unsigned writemask)
 static const char *
 disasm_inst_negate(const struct disasm_inst *inst, bool negate)
 {
+   if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
+      switch (inst->opcode) {
+      case GEN6_OPCODE_AND:
+      case GEN6_OPCODE_NOT:
+      case GEN6_OPCODE_OR:
+      case GEN6_OPCODE_XOR:
+         return (negate) ? "~" : "";
+         break;
+      default:
+         break;
+      }
+   }
+
    return (negate) ? "-" : "";
 }
 
@@ -879,6 +1106,252 @@ disasm_inst_absolute(const struct disasm_inst *inst, bool absolute)
    return (absolute) ? "(abs)" : "";
 }
 
+static const char *
+disasm_inst_mdesc_sampler_op(const struct disasm_inst *inst, int op)
+{
+   switch (op) {
+   case GEN6_MSG_SAMPLER_SAMPLE:       return "sample";
+   case GEN6_MSG_SAMPLER_SAMPLE_B:     return "sample_b";
+   case GEN6_MSG_SAMPLER_SAMPLE_L:     return "sample_l";
+   case GEN6_MSG_SAMPLER_SAMPLE_C:     return "sample_c";
+   case GEN6_MSG_SAMPLER_SAMPLE_D:     return "sample_d";
+   case GEN6_MSG_SAMPLER_SAMPLE_B_C:   return "sample_b_c";
+   case GEN6_MSG_SAMPLER_SAMPLE_L_C:   return "sample_l_c";
+   case GEN6_MSG_SAMPLER_LD:           return "ld";
+   case GEN6_MSG_SAMPLER_GATHER4:      return "gather4";
+   case GEN6_MSG_SAMPLER_LOD:          return "lod";
+   case GEN6_MSG_SAMPLER_RESINFO:      return "resinfo";
+   case GEN6_MSG_SAMPLER_SAMPLEINFO:   return "sampleinfo";
+   case GEN7_MSG_SAMPLER_GATHER4_C:    return "gather4_c";
+   case GEN7_MSG_SAMPLER_GATHER4_PO:   return "gather4_po";
+   case GEN7_MSG_SAMPLER_GATHER4_PO_C: return "gather4_po_c";
+   case GEN7_MSG_SAMPLER_SAMPLE_D_C:   return "sample_d_c";
+   case GEN7_MSG_SAMPLER_SAMPLE_LZ:    return "sample_lz";
+   case GEN7_MSG_SAMPLER_SAMPLE_C_LC:  return "sample_c_lc";
+   case GEN7_MSG_SAMPLER_LD_LZ:        return "ld_lz";
+   case GEN7_MSG_SAMPLER_LD_MCS:       return "ld_mcs";
+   case GEN7_MSG_SAMPLER_LD2DMS:       return "ld2dms";
+   case GEN7_MSG_SAMPLER_LD2DSS:       return "ld2dss";
+   default:                            return "BAD";
+   }
+}
+
+static const char *
+disasm_inst_mdesc_sampler_simd(const struct disasm_inst *inst, int simd)
+{
+   switch (simd) {
+   case GEN6_MSG_SAMPLER_SIMD4X2:   return "SIMD4x2";
+   case GEN6_MSG_SAMPLER_SIMD8:     return "SIMD8";
+   case GEN6_MSG_SAMPLER_SIMD16:    return "SIMD16";
+   case GEN6_MSG_SAMPLER_SIMD32_64: return "SIMD32";
+   default:                         return "BAD";
+   }
+}
+
+static const char *
+disasm_inst_mdesc_urb_op(const struct disasm_inst *inst, int op)
+{
+   if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
+      switch (op) {
+      case GEN7_MSG_URB_WRITE_HWORD:   return "write HWord";
+      case GEN7_MSG_URB_WRITE_OWORD:   return "write OWord";
+      case GEN7_MSG_URB_READ_HWORD:    return "read HWord";
+      case GEN7_MSG_URB_READ_OWORD:    return "read OWord";
+      case GEN7_MSG_URB_ATOMIC_MOV:    return "atomic mov";
+      case GEN7_MSG_URB_ATOMIC_INC:    return "atomic inc";
+      default:                         return "BAD";
+      }
+   } else {
+      switch (op) {
+      case GEN6_MSG_URB_WRITE:         return "urb_write";
+      case GEN6_MSG_URB_FF_SYNC:       return "ff_sync";
+      default:                         return "BAD";
+      }
+   }
+}
+
+static const char *
+disasm_inst_mdesc_dp_op_gen6(const struct disasm_inst *inst,
+                             int sfid, int op)
+{
+   ILO_DEV_ASSERT(inst->dev, 6, 6);
+
+   switch (op) {
+   case GEN6_MSG_DP_OWORD_BLOCK_READ:           return "OWORD block read";
+   case GEN6_MSG_DP_RT_UNORM_READ:              return "RT UNORM read";
+   case GEN6_MSG_DP_OWORD_DUAL_BLOCK_READ:      return "OWORD dual block read";
+   case GEN6_MSG_DP_MEDIA_BLOCK_READ:           return "media block read";
+   case GEN6_MSG_DP_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
+   case GEN6_MSG_DP_DWORD_SCATTERED_READ:       return "DWORD scattered read";
+   case GEN6_MSG_DP_DWORD_ATOMIC_WRITE:         return "DWORD atomic write";
+   case GEN6_MSG_DP_OWORD_BLOCK_WRITE:          return "OWORD block write";
+   case GEN6_MSG_DP_OWORD_DUAL_BLOCK_WRITE:     return "OWORD dual block_write";
+   case GEN6_MSG_DP_MEDIA_BLOCK_WRITE:          return "media block write";
+   case GEN6_MSG_DP_DWORD_SCATTERED_WRITE:      return "DWORD scattered write";
+   case GEN6_MSG_DP_RT_WRITE:                   return "RT write";
+   case GEN6_MSG_DP_SVB_WRITE:                  return "SVB write";
+   case GEN6_MSG_DP_RT_UNORM_WRITE:             return "RT UNORM write";
+   default:                                     return "BAD";
+   }
+}
+
+static const char *
+disasm_inst_mdesc_dp_op_gen7(const struct disasm_inst *inst,
+                             int sfid, int op)
+{
+   ILO_DEV_ASSERT(inst->dev, 7, 7);
+
+   switch (sfid) {
+   case GEN6_SFID_DP_SAMPLER:
+      switch (op) {
+      case GEN7_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ: return "OWORD block read";
+      case GEN7_MSG_DP_SAMPLER_MEDIA_BLOCK_READ:         return "media block read";
+      default:                                           return "BAD";
+      }
+   case GEN6_SFID_DP_RC:
+      switch (op) {
+      case GEN7_MSG_DP_RC_MEDIA_BLOCK_READ:              return "media block read";
+      case GEN7_MSG_DP_RC_TYPED_SURFACE_READ:            return "typed surface read";
+      case GEN7_MSG_DP_RC_TYPED_ATOMIC_OP:               return "typed atomic op";
+      case GEN7_MSG_DP_RC_MEMORY_FENCE:                  return "memory fence";
+      case GEN7_MSG_DP_RC_MEDIA_BLOCK_WRITE:             return "media block write";
+      case GEN7_MSG_DP_RC_RT_WRITE:                      return "RT write";
+      case GEN7_MSG_DP_RC_TYPED_SURFACE_WRITE:           return "typed surface write";
+      default:                                           return "BAD";
+      }
+   case GEN6_SFID_DP_CC:
+      switch (op) {
+      case GEN7_MSG_DP_CC_OWORD_BLOCK_READ:              return "OWROD block read";
+      case GEN7_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ:    return "unaligned OWORD block read";
+      case GEN7_MSG_DP_CC_OWORD_DUAL_BLOCK_READ:         return "OWORD dual block read";
+      case GEN7_MSG_DP_CC_DWORD_SCATTERED_READ:          return "DWORD scattered read";
+      default:                                           return "BAD";
+      }
+   case GEN7_SFID_DP_DC0:
+      switch (op) {
+      case GEN7_MSG_DP_DC0_OWORD_BLOCK_READ:             return "OWORD block read";
+      case GEN7_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ:   return "unaligned OWORD block read";
+      case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ:        return "OWORD dual block read";
+      case GEN7_MSG_DP_DC0_DWORD_SCATTERED_READ:         return "DWORD scattered read";
+      case GEN7_MSG_DP_DC0_BYTE_SCATTERED_READ:          return "BYTE scattered read";
+      case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ:         return "untyped surface read";
+      case GEN7_MSG_DP_DC0_UNTYPED_ATOMIC_OP:            return "untyped atomic op";
+      case GEN7_MSG_DP_DC0_MEMORY_FENCE:                 return "memory fence";
+      case GEN7_MSG_DP_DC0_OWORD_BLOCK_WRITE:            return "OWORD block write";
+      case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE:       return "OWORD dual block write";
+      case GEN7_MSG_DP_DC0_DWORD_SCATTERED_WRITE:        return "OWORD scattered write";
+      case GEN7_MSG_DP_DC0_BYTE_SCATTERED_WRITE:         return "BYTE scattered write";
+      case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE:        return "untyped surface write";
+      default:                                           return "BAD";
+      }
+   default:                                              return "BAD";
+   }
+}
+
+static const char *
+disasm_inst_mdesc_dp_op_gen75(const struct disasm_inst *inst,
+                              int sfid, int op)
+{
+   ILO_DEV_ASSERT(inst->dev, 7.5, 8);
+
+   switch (sfid) {
+   case GEN6_SFID_DP_SAMPLER:
+      switch (op) {
+      case GEN75_MSG_DP_SAMPLER_READ_SURFACE_INFO:          return "read surface info";
+      case GEN75_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
+      case GEN75_MSG_DP_SAMPLER_MEDIA_BLOCK_READ:           return "media block read";
+      default:                                              return "BAD";
+      }
+
+   case GEN6_SFID_DP_RC:
+      switch (op) {
+      case GEN75_MSG_DP_RC_MEDIA_BLOCK_READ:                return "media block read";
+      case GEN75_MSG_DP_RC_MEMORY_FENCE:                    return "memory fence";
+      case GEN75_MSG_DP_RC_MEDIA_BLOCK_WRITE:               return "media block write";
+      case GEN75_MSG_DP_RC_RT_WRITE:                        return "RT write";
+      default:                                              return "BAD";
+      }
+   case GEN6_SFID_DP_CC:
+      switch (op) {
+      case GEN75_MSG_DP_CC_OWORD_BLOCK_READ:                return "OWROD block read";
+      case GEN75_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ:      return "unaligned OWORD block read";
+      case GEN75_MSG_DP_CC_OWORD_DUAL_BLOCK_READ:           return "OWORD dual block read";
+      case GEN75_MSG_DP_CC_DWORD_SCATTERED_READ:            return "DWORD scattered read";
+      default:                                              return "BAD";
+      }
+   case GEN7_SFID_DP_DC0:
+      switch (op) {
+      case GEN75_MSG_DP_DC0_OWORD_BLOCK_READ:               return "OWORD block read";
+      case GEN75_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ:     return "unaligned OWORD block read";
+      case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ:          return "OWORD dual block read";
+      case GEN75_MSG_DP_DC0_DWORD_SCATTERED_READ:           return "DWORD scattered read";
+      case GEN75_MSG_DP_DC0_BYTE_SCATTERED_READ:            return "BYTE scattered read";
+      case GEN75_MSG_DP_DC0_MEMORY_FENCE:                   return "memory fence";
+      case GEN75_MSG_DP_DC0_OWORD_BLOCK_WRITE:              return "OWORD block write";
+      case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE:         return "OWORD dual block write";
+      case GEN75_MSG_DP_DC0_DWORD_SCATTERED_WRITE:          return "OWORD scattered write";
+      case GEN75_MSG_DP_DC0_BYTE_SCATTERED_WRITE:           return "BYTE scattered write";
+      default:                                              return "BAD";
+      }
+   case GEN75_SFID_DP_DC1:
+      switch (op) {
+      case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ:           return "untyped surface read";
+      case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP:              return "DC untyped atomic op";
+      case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP_SIMD4X2:      return "DC untyped 4x2 atomic op";
+      case GEN75_MSG_DP_DC1_MEDIA_BLOCK_READ:               return "DC media block read";
+      case GEN75_MSG_DP_DC1_TYPED_SURFACE_READ:             return "DC typed surface read";
+      case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP:                return "DC typed atomic";
+      case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP_SIMD4X2:        return "DC typed 4x2 atomic op";
+      case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE:          return "DC untyped surface write";
+      case GEN75_MSG_DP_DC1_MEDIA_BLOCK_WRITE:              return "DC media block write";
+      case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP:              return "DC atomic counter op";
+      case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP_SIMD4X2:      return "DC 4x2 atomic counter op";
+      case GEN75_MSG_DP_DC1_TYPED_SURFACE_WRITE:            return "DC typed surface write";
+      default:                                              return "BAD";
+      }
+   default:                                              return "BAD";
+   }
+}
+
+static const char *
+disasm_inst_mdesc_dp_op(const struct disasm_inst *inst, int sfid, int op)
+{
+   switch (ilo_dev_gen(inst->dev)) {
+   case ILO_GEN(8):
+   case ILO_GEN(7.5):   return disasm_inst_mdesc_dp_op_gen75(inst, sfid, op);
+   case ILO_GEN(7):     return disasm_inst_mdesc_dp_op_gen7(inst, sfid, op);
+   case ILO_GEN(6):     return disasm_inst_mdesc_dp_op_gen6(inst, sfid, op);
+   default:             return "BAD";
+   }
+}
+
+static const char *
+disasm_inst_mdesc_dp_untyped_surface_simd_mode(const struct disasm_inst *inst,
+                                               uint32_t mdesc)
+{
+   switch (mdesc & GEN7_MSG_DP_UNTYPED_MODE__MASK) {
+   case GEN7_MSG_DP_UNTYPED_MODE_SIMD4X2: return "SIMD4x2";
+   case GEN7_MSG_DP_UNTYPED_MODE_SIMD16:  return "SIMD16";
+   case GEN7_MSG_DP_UNTYPED_MODE_SIMD8:   return "SIMD8";
+   default:                               return "BAD";
+   }
+}
+
+static const char *
+disasm_inst_mdesc_dp_rt_write_simd_mode(const struct disasm_inst *inst,
+                                        uint32_t mdesc)
+{
+   switch (mdesc & GEN6_MSG_DP_RT_MODE__MASK) {
+   case GEN6_MSG_DP_RT_MODE_SIMD16:             return "SIMD16";
+   case GEN6_MSG_DP_RT_MODE_SIMD16_REPDATA:     return "SIMD16/RepData";
+   case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_LO:   return "SIMD8/DualSrcLow";
+   case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_HI:   return "SIMD8/DualSrcHigh";
+   case GEN6_MSG_DP_RT_MODE_SIMD8_LO:           return "SIMD8";
+   case GEN6_MSG_DP_RT_MODE_SIMD8_IMAGE_WR:     return "SIMD8/ImageWrite";
+   default:                                     return "BAD";
+   }
+}
+
 static bool
 disasm_inst_is_null(const struct disasm_inst *inst,
                     const struct disasm_operand *operand)
@@ -1019,28 +1492,28 @@ disasm_printer_add_operand(struct disasm_printer *printer,
    if (operand->file == GEN6_FILE_IMM) {
       switch (operand->type) {
       case GEN6_TYPE_UD:
-         disasm_printer_add(printer, "0x%08xUD", inst->u.imm32);
+         disasm_printer_add(printer, "0x%08xUD", inst->u.ud);
          break;
       case GEN6_TYPE_D:
-         disasm_printer_add(printer, "%dD", inst->u.imm32);
+         disasm_printer_add(printer, "%dD", inst->u.d);
          break;
       case GEN6_TYPE_UW:
-         disasm_printer_add(printer, "0x%04xUW", (uint16_t) inst->u.imm32);
+         disasm_printer_add(printer, "0x%04xUW", inst->u.uw);
          break;
       case GEN6_TYPE_W:
-         disasm_printer_add(printer, "%dW", (int16_t) inst->u.imm32);
+         disasm_printer_add(printer, "%dW", inst->u.w);
          break;
       case GEN6_TYPE_UV_IMM:
-         disasm_printer_add(printer, "0x%08xUV", inst->u.imm32);
+         disasm_printer_add(printer, "0x%08xUV", inst->u.ud);
          break;
       case GEN6_TYPE_VF_IMM:
          disasm_printer_add(printer, "Vector Float");
          break;
       case GEN6_TYPE_V_IMM:
-         disasm_printer_add(printer, "0x%08xV", inst->u.imm32);
+         disasm_printer_add(printer, "0x%08xV", inst->u.ud);
          break;
       case GEN6_TYPE_F:
-         disasm_printer_add(printer, "%-gF", uif(inst->u.imm32));
+         disasm_printer_add(printer, "%-gF", uif(inst->u.f));
          break;
       default:
          disasm_printer_add(printer, "BAD");
@@ -1164,10 +1637,12 @@ disasm_printer_add_mdesc_sampler(struct disasm_printer *printer,
       simd = GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_SIMD);
    }
 
-   disasm_printer_add(printer, " (%d, %d, %d, %d)",
-         GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_SURFACE),
+   disasm_printer_add(printer,
+         "%s %s samp %d surf %d",
+         disasm_inst_mdesc_sampler_op(inst, op),
+         disasm_inst_mdesc_sampler_simd(inst, simd),
          GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_INDEX),
-         op, simd);
+         GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_SURFACE));
 }
 
 static void
@@ -1175,34 +1650,21 @@ disasm_printer_add_mdesc_urb(struct disasm_printer *printer,
                              const struct disasm_inst *inst,
                              uint32_t mdesc)
 {
-   const char *op;
-   int offset;
+   int op, offset;
    bool interleaved, complete, allocate, used;
 
    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
-      switch (GEN_EXTRACT(mdesc, GEN7_MSG_URB_OP)) {
-      case GEN7_MSG_URB_WRITE_HWORD:   op = "write HWord";  break;
-      case GEN7_MSG_URB_WRITE_OWORD:   op = "write OWord";  break;
-      case GEN7_MSG_URB_READ_HWORD:    op = "read HWord";   break;
-      case GEN7_MSG_URB_READ_OWORD:    op = "read OWord";   break;
-      case GEN7_MSG_URB_ATOMIC_MOV:    op = "atomic mov";   break;
-      case GEN7_MSG_URB_ATOMIC_INC:    op = "atomic inc";   break;
-      default:                         op = "BAD";          break;
-      }
-
+      op = GEN_EXTRACT(mdesc, GEN7_MSG_URB_OP);
       offset = GEN_EXTRACT(mdesc, GEN7_MSG_URB_GLOBAL_OFFSET);
       interleaved = mdesc & GEN7_MSG_URB_INTERLEAVED;
-      complete = mdesc & GEN7_MSG_URB_COMPLETE;
+
+      complete = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ?
+         false : (mdesc & GEN7_MSG_URB_COMPLETE);
 
       allocate = false;
       used = false;
    } else {
-      switch (GEN_EXTRACT(mdesc, GEN6_MSG_URB_OP)) {
-      case GEN6_MSG_URB_WRITE:         op = "urb_write";    break;
-      case GEN6_MSG_URB_FF_SYNC:       op = "ff_sync";      break;
-      default:                         op = "BAD";          break;
-      }
-
+      op = GEN_EXTRACT(mdesc, GEN6_MSG_URB_OP);
       offset = GEN_EXTRACT(mdesc, GEN6_MSG_URB_OFFSET);
       interleaved = mdesc & GEN6_MSG_URB_INTERLEAVED;
       complete = mdesc & GEN6_MSG_URB_COMPLETE;
@@ -1211,13 +1673,45 @@ disasm_printer_add_mdesc_urb(struct disasm_printer *printer,
       used = mdesc & GEN6_MSG_URB_USED;
    }
 
-   disasm_printer_add(printer, " %d %s%s%s%s%s", offset, op,
+   disasm_printer_add(printer, "%s offset %d%s%s%s%s",
+         disasm_inst_mdesc_urb_op(inst, op),
+         offset,
          (interleaved) ? " interleave" : "",
          (allocate) ? " allocate" : "",
          (used) ? " used" : "",
          (complete) ? " complete" : "");
 }
 
+static void
+disasm_printer_add_mdesc_spawner(struct disasm_printer *printer,
+                                 const struct disasm_inst *inst,
+                                 uint32_t mdesc)
+{
+   const char *requester, *op;
+
+   switch (mdesc & GEN6_MSG_TS_REQUESTER_TYPE__MASK) {
+   case GEN6_MSG_TS_REQUESTER_TYPE_ROOT:  requester = "root";  break;
+   case GEN6_MSG_TS_REQUESTER_TYPE_CHILD: requester = "child"; break;
+   default:                               requester = "BAD";   break;
+   }
+
+   switch (mdesc & GEN6_MSG_TS_OPCODE__MASK) {
+   case GEN6_MSG_TS_OPCODE_DEREF:
+      op = (mdesc & GEN6_MSG_TS_RESOURCE_SELECT_NO_DEREF) ?
+         "no deref" : "deref";
+      break;
+   case GEN6_MSG_TS_OPCODE_SPAWN:
+      op = (mdesc & GEN6_MSG_TS_RESOURCE_SELECT_ROOT) ?
+         "spawn root" : "spawn child";
+      break;
+   default:
+      op = "BAD";
+      break;
+   }
+
+   disasm_printer_add(printer, "%s thread %s", requester, op);
+}
+
 static void
 disasm_printer_add_mdesc_dp_sampler(struct disasm_printer *printer,
                                     const struct disasm_inst *inst,
@@ -1228,10 +1722,72 @@ disasm_printer_add_mdesc_dp_sampler(struct disasm_printer *printer,
    const bool write_commit = (ilo_dev_gen(inst->dev) == ILO_GEN(6)) ?
          (mdesc & GEN6_MSG_DP_SEND_WRITE_COMMIT) : 0;
 
-   disasm_printer_add(printer, " (%d, %d, %d, %d)",
-         GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE),
+   disasm_printer_add(printer, "%s block size %d commit %d surf %d",
+         disasm_inst_mdesc_dp_op(inst, GEN6_SFID_DP_SAMPLER, op),
          GEN_EXTRACT(mdesc, GEN6_MSG_DP_OWORD_BLOCK_SIZE),
-         op, write_commit);
+         write_commit,
+         GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
+}
+
+static void
+disasm_printer_add_mdesc_dp_dc0(struct disasm_printer *printer,
+                                const struct disasm_inst *inst,
+                                uint32_t mdesc)
+{
+   const int op = GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP);
+
+   ILO_DEV_ASSERT(inst->dev, 7, 7.5);
+
+   if (ilo_dev_gen(inst->dev) >= ILO_GEN(7.5)) {
+      disasm_printer_add(printer, "%s ctrl 0x%x surf %d",
+            disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op),
+            GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL),
+            GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
+   } else {
+      switch (op) {
+      case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ:
+      case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE:
+         disasm_printer_add(printer, "%s %s mask 0x%x surf %d",
+               disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op),
+               disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst, mdesc),
+               GEN_EXTRACT(mdesc, GEN7_MSG_DP_UNTYPED_MASK),
+               GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
+         break;
+      default:
+         disasm_printer_add(printer, "%s ctrl 0x%x surf %d",
+               disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op),
+               GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL),
+               GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
+         break;
+      }
+   }
+}
+
+static void
+disasm_printer_add_mdesc_dp_dc1(struct disasm_printer *printer,
+                                const struct disasm_inst *inst,
+                                uint32_t mdesc)
+{
+   const int op = GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP);
+
+   ILO_DEV_ASSERT(inst->dev, 7.5, 7.5);
+
+   switch (op) {
+   case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ:
+   case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE:
+      disasm_printer_add(printer, "%s %s mask 0x%x surf %d",
+            disasm_inst_mdesc_dp_op(inst, GEN75_SFID_DP_DC1, op),
+            disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst, mdesc),
+            GEN_EXTRACT(mdesc, GEN7_MSG_DP_UNTYPED_MASK),
+            GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
+      break;
+   default:
+      disasm_printer_add(printer, "%s ctrl 0x%x surf %d",
+            disasm_inst_mdesc_dp_op(inst, GEN75_SFID_DP_DC1, op),
+            GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL),
+            GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
+      break;
+   }
 }
 
 static void
@@ -1241,75 +1797,28 @@ disasm_printer_add_mdesc_dp_rc(struct disasm_printer *printer,
 {
    const int op = (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) ?
       GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP) : GEN_EXTRACT(mdesc, GEN6_MSG_DP_OP);
-   const char *str;
    bool is_rt_write;
 
-   if (ilo_dev_gen(inst->dev) >= ILO_GEN(7.5)) {
-      switch (op) {
-      case GEN75_MSG_DP_RC_MEDIA_BLOCK_READ:       str = "media block read";           break;
-      case GEN75_MSG_DP_RC_MEMORY_FENCE:           str = "memory fence";               break;
-      case GEN75_MSG_DP_RC_MEDIA_BLOCK_WRITE:      str = "media block write";          break;
-      case GEN75_MSG_DP_RC_RT_WRITE:               str = "RT write";                   break;
-      default:                                     str = "BAD";                        break;
-      }
-
+   if (ilo_dev_gen(inst->dev) >= ILO_GEN(7.5))
       is_rt_write = (op == GEN75_MSG_DP_RC_RT_WRITE);
-   } else if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
-      switch (op) {
-      case GEN7_MSG_DP_RC_MEDIA_BLOCK_READ:        str = "media block read";           break;
-      case GEN7_MSG_DP_RC_TYPED_SURFACE_READ:      str = "typed surface read";         break;
-      case GEN7_MSG_DP_RC_TYPED_ATOMIC_OP:         str = "typed atomic op";            break;
-      case GEN7_MSG_DP_RC_MEMORY_FENCE:            str = "memory fence";               break;
-      case GEN7_MSG_DP_RC_MEDIA_BLOCK_WRITE:       str = "media block write";          break;
-      case GEN7_MSG_DP_RC_RT_WRITE:                str = "RT write";                   break;
-      case GEN7_MSG_DP_RC_TYPED_SURFACE_WRITE:     str = "typed surface write";        break;
-      default:                                     str = "BAD";                        break;
-      }
-
+   else if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
       is_rt_write = (op == GEN7_MSG_DP_RC_RT_WRITE);
-   } else {
-      switch (op) {
-      case GEN6_MSG_DP_OWORD_BLOCK_READ:           str = "OWORD block read";           break;
-      case GEN6_MSG_DP_RT_UNORM_READ:              str = "RT UNORM read";              break;
-      case GEN6_MSG_DP_OWORD_DUAL_BLOCK_READ:      str = "OWORD dual block read";      break;
-      case GEN6_MSG_DP_MEDIA_BLOCK_READ:           str = "media block read";           break;
-      case GEN6_MSG_DP_UNALIGNED_OWORD_BLOCK_READ: str = "unaligned OWORD block read"; break;
-      case GEN6_MSG_DP_DWORD_SCATTERED_READ:       str = "DWORD scattered read";       break;
-      case GEN6_MSG_DP_DWORD_ATOMIC_WRITE:         str = "DWORD atomic write";         break;
-      case GEN6_MSG_DP_OWORD_BLOCK_WRITE:          str = "OWORD block write";          break;
-      case GEN6_MSG_DP_OWORD_DUAL_BLOCK_WRITE:     str = "OWORD dual block_write";     break;
-      case GEN6_MSG_DP_MEDIA_BLOCK_WRITE:          str = "media block write";          break;
-      case GEN6_MSG_DP_DWORD_SCATTERED_WRITE:      str = "DWORD scattered write";      break;
-      case GEN6_MSG_DP_RT_WRITE:                   str = "RT write";                   break;
-      case GEN6_MSG_DP_SVB_WRITE:                  str = "SVB write";                  break;
-      case GEN6_MSG_DP_RT_UNORM_WRITE:             str = "RT UNORM write";             break;
-      default:                                     str = "BAD";                        break;
-      }
-
+   else
       is_rt_write = (op == GEN6_MSG_DP_RT_WRITE);
-   }
 
-   disasm_printer_add(printer, " %s", str);
+   disasm_printer_add(printer, "%s",
+         disasm_inst_mdesc_dp_op(inst, GEN6_SFID_DP_RC, op));
 
    if (is_rt_write) {
-      switch (mdesc & GEN6_MSG_DP_RT_MODE__MASK) {
-      case GEN6_MSG_DP_RT_MODE_SIMD16:             str = "SIMD16";            break;
-      case GEN6_MSG_DP_RT_MODE_SIMD16_REPDATA:     str = "SIMD16/RepData";    break;
-      case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_LO:   str = "SIMD8/DualSrcLow";  break;
-      case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_HI:   str = "SIMD8/DualSrcHigh"; break;
-      case GEN6_MSG_DP_RT_MODE_SIMD8_LO:           str = "SIMD8";             break;
-      case GEN6_MSG_DP_RT_MODE_SIMD8_IMAGE_WR:     str = "SIMD8/ImageWrite";  break;
-      default:                                     str = "BAD";               break;
-      }
-
-      disasm_printer_add(printer, " %s%s%s%s", str,
-            (mdesc & GEN6_MSG_DP_SLOTGRP_HI) ? " Hi" : "",
+      disasm_printer_add(printer, " %s%s%s%s",
+            disasm_inst_mdesc_dp_rt_write_simd_mode(inst, mdesc),
+            (mdesc & GEN6_MSG_DP_RT_SLOTGRP_HI) ? " Hi" : "",
             (mdesc & GEN6_MSG_DP_RT_LAST) ? " LastRT" : "",
             (ilo_dev_gen(inst->dev) == ILO_GEN(6) &&
              (mdesc & GEN6_MSG_DP_SEND_WRITE_COMMIT)) ? " WriteCommit" : "");
    }
 
-   disasm_printer_add(printer, " Surface = %d",
+   disasm_printer_add(printer, " surf %d",
          GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
 }
 
@@ -1317,13 +1826,13 @@ static void
 disasm_printer_add_mdesc(struct disasm_printer *printer,
                          const struct disasm_inst *inst)
 {
-   const uint32_t mdesc = inst->u.imm32;
+   const uint32_t mdesc = inst->u.ud;
 
    assert(inst->opcode == GEN6_OPCODE_SEND ||
           inst->opcode == GEN6_OPCODE_SENDC);
    assert(inst->src1.base.file == GEN6_FILE_IMM);
 
-   disasm_printer_add(printer, "            %s", disasm_inst_sfid(inst));
+   disasm_printer_add(printer, "            %s (", disasm_inst_sfid(inst));
 
    switch (inst->sfid) {
    case GEN6_SFID_SAMPLER:
@@ -1338,15 +1847,22 @@ disasm_printer_add_mdesc(struct disasm_printer *printer,
    case GEN6_SFID_URB:
       disasm_printer_add_mdesc_urb(printer, inst, mdesc);
       break;
-   case GEN6_SFID_DP_CC:
+   case GEN6_SFID_SPAWNER:
+      disasm_printer_add_mdesc_spawner(printer, inst, mdesc);
+      break;
    case GEN7_SFID_DP_DC0:
-   case GEN7_SFID_PI:
+      disasm_printer_add_mdesc_dp_dc0(printer, inst, mdesc);
+      break;
    case GEN75_SFID_DP_DC1:
+      disasm_printer_add_mdesc_dp_dc1(printer, inst, mdesc);
+      break;
+   case GEN6_SFID_DP_CC:
+   case GEN7_SFID_PI:
    default:
       break;
    }
 
-   disasm_printer_add(printer, " mlen %d rlen %d",
+   disasm_printer_add(printer, ") mlen %d rlen %d",
          GEN_EXTRACT(mdesc, GEN6_MSG_MLEN),
          GEN_EXTRACT(mdesc, GEN6_MSG_RLEN));
 }
@@ -1364,14 +1880,19 @@ disasm_printer_print_inst(struct disasm_printer *printer,
 
    if (inst->has_jip || inst->has_uip) {
       if (inst->has_jip) {
+         const int32_t jip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ?
+            inst->u.ip32.jip : inst->u.ip16.jip;
+
          disasm_printer_column(printer, col++);
-         disasm_printer_add(printer, "JIP: %d", (int16_t) inst->u.imm32);
+         disasm_printer_add(printer, "JIP: %d", jip);
       }
 
       if (inst->has_uip) {
+         const int32_t uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ?
+            inst->u.ip32.uip : inst->u.ip16.uip;
+
          disasm_printer_column(printer, col++);
-         disasm_printer_add(printer, "UIP: %d",
-               (int16_t) (inst->u.imm32 >> 16));
+         disasm_printer_add(printer, "UIP: %d", uip);
       }
    } else {
       const int src_count = disasm_opcode_table[inst->opcode].src_count;
@@ -1414,8 +1935,181 @@ disasm_printer_print_inst(struct disasm_printer *printer,
    ilo_printf("%s\n", disasm_printer_get_string(printer));
 }
 
+static void
+disasm_uncompact_3src(const struct ilo_dev *dev,
+                      uint64_t compact, uint32_t *dw)
+{
+   const struct toy_compaction_table *tbl =
+      toy_compiler_get_compaction_table(dev);
+   uint32_t src[3], tmp;
+   uint64_t tmp64;
+
+   ILO_DEV_ASSERT(dev, 8, 8);
+
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_OPCODE);
+   dw[0] = GEN_SHIFT32(tmp, GEN6_INST_OPCODE);
+
+   /* ControlIndex */
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_CONTROL_INDEX);
+   tmp = tbl->control_3src[tmp];
+
+   dw[0] |= (tmp & 0x1fffff) << GEN6_INST_ACCESSMODE__SHIFT;
+   dw[1] = (tmp >> 21) & ((ilo_dev_gen(dev) >= ILO_GEN(9)) ? 0x1f : 0x7);
+
+   /* SourceIndex */
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SOURCE_INDEX);
+   tmp64 = tbl->source_3src[tmp];
+
+   dw[1] |= (tmp64 & 0x7ffff) << 5;
+   src[0] = ((tmp64 >> 19) & 0xff) << 1;
+   src[1] = ((tmp64 >> 27) & 0xff) << 1;
+   src[2] = ((tmp64 >> 35) & 0xff) << 1;
+   if (ilo_dev_gen(dev) >= ILO_GEN(9)) {
+      src[0] |= ((tmp64 >> 43) & 0x3) << 19;
+      src[1] |= ((tmp64 >> 45) & 0x3) << 19;
+      src[2] |= ((tmp64 >> 47) & 0x3) << 19;
+   } else {
+      src[0] |= ((tmp64 >> 43) & 0x1) << 19;
+      src[1] |= ((tmp64 >> 44) & 0x1) << 19;
+      src[2] |= ((tmp64 >> 45) & 0x1) << 19;
+   }
+
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_DST_REG);
+   dw[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_DST_REG);
+
+   if (compact & GEN8_COMPACT_3SRC_SRC0_REPCTRL)
+      src[0] |= GEN6_3SRC_SRC_REPCTRL;
+
+   assert(compact & GEN8_COMPACT_3SRC_CMPTCTRL);
+
+   if (compact & GEN8_COMPACT_3SRC_DEBUGCTRL)
+      dw[0] |= GEN6_INST_DEBUGCTRL;
+   if (compact & GEN8_COMPACT_3SRC_SATURATE)
+      dw[0] |= GEN6_INST_SATURATE;
+
+   if (compact & GEN8_COMPACT_3SRC_SRC1_REPCTRL)
+      src[1] |= GEN6_3SRC_SRC_REPCTRL;
+   if (compact & GEN8_COMPACT_3SRC_SRC2_REPCTRL)
+      src[2] |= GEN6_3SRC_SRC_REPCTRL;
+
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC0_SUBREG);
+   src[0] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG);
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC1_SUBREG);
+   src[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG);
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC2_SUBREG);
+   src[2] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG);
+
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC0_REG);
+   src[0] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG);
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC1_REG);
+   src[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG);
+   tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC2_REG);
+   src[2] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG);
+
+   tmp64 = (uint64_t) src[2] << 42 |
+           (uint64_t) src[1] << 21 |
+           (uint64_t) src[0];
+   dw[2] = (uint32_t) tmp64;
+   dw[3] = (uint32_t) (tmp64 >> 32);
+}
+
+static void
+disasm_uncompact(const struct ilo_dev *dev,
+                 uint64_t compact, uint32_t *dw)
+{
+   const struct toy_compaction_table *tbl =
+      toy_compiler_get_compaction_table(dev);
+   bool src_is_imm;
+   uint32_t tmp;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_OPCODE);
+   if (disasm_opcode_table[tmp].src_count == 3) {
+      disasm_uncompact_3src(dev, compact, dw);
+      return;
+   }
+
+   memset(dw, 0, sizeof(*dw) * 4);
+
+   dw[0] |= GEN_SHIFT32(tmp, GEN6_INST_OPCODE);
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(7) && (compact & GEN6_COMPACT_DEBUGCTRL))
+      dw[0] |= GEN6_INST_DEBUGCTRL;
+
+   /* ControlIndex */
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_CONTROL_INDEX);
+   tmp = tbl->control[tmp];
+
+   dw[0] |= (tmp & 0xffff) << GEN6_INST_ACCESSMODE__SHIFT;
+   if (tmp & 0x10000)
+      dw[0] |= GEN6_INST_SATURATE;
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(7))
+      dw[2] |= (tmp >> 17) << GEN6_INST_FLAG_SUBREG__SHIFT;
+
+   /* DataTypeIndex */
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_DATATYPE_INDEX);
+   tmp = tbl->datatype[tmp];
+
+   dw[1] |= (tmp & 0x7fff) << GEN6_INST_DST_FILE__SHIFT;
+   dw[1] |= (tmp >> 15) << GEN6_INST_DST_HORZSTRIDE__SHIFT;
+
+   /* SubRegIndex */
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SUBREG_INDEX);
+   tmp = tbl->subreg[tmp];
+
+   dw[1] |= (tmp & 0x1f) << 16;
+   dw[2] |= ((tmp >> 5) & 0x1f);
+   dw[3] |= ((tmp >> 10) & 0x1f);
+
+   if (compact & GEN6_COMPACT_ACCWRCTRL)
+      dw[0] |= GEN6_INST_ACCWRCTRL;
+
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_CONDMODIFIER);
+   dw[0] |= GEN_SHIFT32(tmp, GEN6_INST_CONDMODIFIER);
+
+   if (ilo_dev_gen(dev) == ILO_GEN(6)) {
+      tmp = GEN_EXTRACT(compact, GEN6_COMPACT_FLAG_SUBREG);
+      dw[2] |= GEN_SHIFT32(compact, GEN6_INST_FLAG_SUBREG);
+   }
+
+   assert(compact & GEN6_COMPACT_CMPTCTRL);
+
+   /* Src0Index */
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC0_INDEX);
+   tmp = tbl->src[tmp];
+   dw[2] |= tmp << 13;
+
+   src_is_imm = (GEN_EXTRACT(dw[1], GEN6_INST_SRC0_FILE) == GEN6_FILE_IMM) ||
+                (GEN_EXTRACT(dw[1], GEN6_INST_SRC1_FILE) == GEN6_FILE_IMM);
+
+   /* Src1Index */
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC1_INDEX);
+   if (src_is_imm) {
+      if (tmp & 0x10)
+         tmp |= 0xfffff0;
+      dw[3] |= tmp << 8;
+   } else {
+      tmp = tbl->src[tmp];
+      dw[3] |= tmp << 13;
+   }
+
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_DST_REG);
+   dw[1] |= GEN_SHIFT32(tmp, GEN6_INST_DST_REG);
+
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC0_REG);
+   dw[2] |= GEN_SHIFT32(tmp, GEN6_INST_SRC_REG);
+
+   tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC1_REG);
+   if (src_is_imm)
+      dw[3] |= tmp;
+   else
+      dw[3] |= GEN_SHIFT32(tmp, GEN6_INST_SRC_REG);
+}
+
 void
-toy_compiler_disassemble(const struct ilo_dev_info *dev,
+toy_compiler_disassemble(const struct ilo_dev *dev,
                          const void *kernel, int size,
                          bool dump_hex)
 {
@@ -1437,8 +2131,8 @@ toy_compiler_disassemble(const struct ilo_dev_info *dev,
          break;
 
       if (compacted) {
-         /* no compaction support yet */
-         memset(temp, 0, sizeof(temp));
+         const uint64_t compact = (uint64_t) dw[1] << 32 | dw[0];
+         disasm_uncompact(dev, compact, temp);
          dw = temp;
       }