softpipe: Factor out evaluation of the source indices
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_exec.c
index 48d91af3e16e9e2b095f270076b9715b57a49895..d191ded39938dd8ab399210b859f157f7b286f8f 100644 (file)
@@ -846,40 +846,40 @@ static void
 micro_u64div(union tgsi_double_channel *dst,
              const union tgsi_double_channel *src)
 {
-   dst->u64[0] = src[0].u64[0] / src[1].u64[0];
-   dst->u64[1] = src[0].u64[1] / src[1].u64[1];
-   dst->u64[2] = src[0].u64[2] / src[1].u64[2];
-   dst->u64[3] = src[0].u64[3] / src[1].u64[3];
+   dst->u64[0] = src[1].u64[0] ? src[0].u64[0] / src[1].u64[0] : ~0ull;
+   dst->u64[1] = src[1].u64[1] ? src[0].u64[1] / src[1].u64[1] : ~0ull;
+   dst->u64[2] = src[1].u64[2] ? src[0].u64[2] / src[1].u64[2] : ~0ull;
+   dst->u64[3] = src[1].u64[3] ? src[0].u64[3] / src[1].u64[3] : ~0ull;
 }
 
 static void
 micro_i64div(union tgsi_double_channel *dst,
              const union tgsi_double_channel *src)
 {
-   dst->i64[0] = src[0].i64[0] / src[1].i64[0];
-   dst->i64[1] = src[0].i64[1] / src[1].i64[1];
-   dst->i64[2] = src[0].i64[2] / src[1].i64[2];
-   dst->i64[3] = src[0].i64[3] / src[1].i64[3];
+   dst->i64[0] = src[1].i64[0] ? src[0].i64[0] / src[1].i64[0] : 0;
+   dst->i64[1] = src[1].i64[1] ? src[0].i64[1] / src[1].i64[1] : 0;
+   dst->i64[2] = src[1].i64[2] ? src[0].i64[2] / src[1].i64[2] : 0;
+   dst->i64[3] = src[1].i64[3] ? src[0].i64[3] / src[1].i64[3] : 0;
 }
 
 static void
 micro_u64mod(union tgsi_double_channel *dst,
              const union tgsi_double_channel *src)
 {
-   dst->u64[0] = src[0].u64[0] % src[1].u64[0];
-   dst->u64[1] = src[0].u64[1] % src[1].u64[1];
-   dst->u64[2] = src[0].u64[2] % src[1].u64[2];
-   dst->u64[3] = src[0].u64[3] % src[1].u64[3];
+   dst->u64[0] = src[1].u64[0] ? src[0].u64[0] % src[1].u64[0] : ~0ull;
+   dst->u64[1] = src[1].u64[1] ? src[0].u64[1] % src[1].u64[1] : ~0ull;
+   dst->u64[2] = src[1].u64[2] ? src[0].u64[2] % src[1].u64[2] : ~0ull;
+   dst->u64[3] = src[1].u64[3] ? src[0].u64[3] % src[1].u64[3] : ~0ull;
 }
 
 static void
 micro_i64mod(union tgsi_double_channel *dst,
              const union tgsi_double_channel *src)
 {
-   dst->i64[0] = src[0].i64[0] % src[1].i64[0];
-   dst->i64[1] = src[0].i64[1] % src[1].i64[1];
-   dst->i64[2] = src[0].i64[2] % src[1].i64[2];
-   dst->i64[3] = src[0].i64[3] % src[1].i64[3];
+   dst->i64[0] = src[1].i64[0] ? src[0].i64[0] % src[1].i64[0] : ~0ll;
+   dst->i64[1] = src[1].i64[1] ? src[0].i64[1] % src[1].i64[1] : ~0ll;
+   dst->i64[2] = src[1].i64[2] ? src[0].i64[2] % src[1].i64[2] : ~0ll;
+   dst->i64[3] = src[1].i64[3] ? src[0].i64[3] % src[1].i64[3] : ~0ll;
 }
 
 static void
@@ -948,7 +948,22 @@ enum tgsi_exec_datatype {
 #define TEMP_OUTPUT_C      TGSI_EXEC_TEMP_OUTPUT_C
 #define TEMP_PRIMITIVE_I   TGSI_EXEC_TEMP_PRIMITIVE_I
 #define TEMP_PRIMITIVE_C   TGSI_EXEC_TEMP_PRIMITIVE_C
-
+#define TEMP_PRIMITIVE_S1_I   TGSI_EXEC_TEMP_PRIMITIVE_S1_I
+#define TEMP_PRIMITIVE_S1_C   TGSI_EXEC_TEMP_PRIMITIVE_S1_C
+#define TEMP_PRIMITIVE_S2_I   TGSI_EXEC_TEMP_PRIMITIVE_S2_I
+#define TEMP_PRIMITIVE_S2_C   TGSI_EXEC_TEMP_PRIMITIVE_S2_C
+#define TEMP_PRIMITIVE_S3_I   TGSI_EXEC_TEMP_PRIMITIVE_S3_I
+#define TEMP_PRIMITIVE_S3_C   TGSI_EXEC_TEMP_PRIMITIVE_S3_C
+
+static const struct {
+   int idx;
+   int chan;
+} temp_prim_idxs[] = {
+   { TEMP_PRIMITIVE_I, TEMP_PRIMITIVE_C },
+   { TEMP_PRIMITIVE_S1_I, TEMP_PRIMITIVE_S1_C },
+   { TEMP_PRIMITIVE_S2_I, TEMP_PRIMITIVE_S2_C },
+   { TEMP_PRIMITIVE_S3_I, TEMP_PRIMITIVE_S3_C },
+};
 
 /** The execution mask depends on the conditional mask and the loop mask */
 #define UPDATE_EXEC_MASK(MACH) \
@@ -1223,7 +1238,17 @@ tgsi_exec_machine_bind_shader(
          {
             uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
             assert( size <= 4 );
-            assert( mach->ImmLimit + 1 <= TGSI_EXEC_NUM_IMMEDIATES );
+            if (mach->ImmLimit >= mach->ImmsReserved) {
+               unsigned newReserved = mach->ImmsReserved ? 2 * mach->ImmsReserved : 128;
+               float4 *imms = REALLOC(mach->Imms, mach->ImmsReserved, newReserved * sizeof(float4));
+               if (imms) {
+                  mach->ImmsReserved = newReserved;
+                  mach->Imms = imms;
+               } else {
+                  debug_printf("Unable to (re)allocate space for immidiate constants\n");
+                  break;
+               }
+            }
 
             for( i = 0; i < size; i++ ) {
                mach->Imms[mach->ImmLimit][i] = 
@@ -1291,7 +1316,6 @@ tgsi_exec_machine_create(enum pipe_shader_type shader_type)
    mach->ShaderType = shader_type;
    mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR];
    mach->MaxGeometryShaderOutputs = TGSI_MAX_TOTAL_VERTICES;
-   mach->Predicates = &mach->Temps[TGSI_EXEC_TEMP_P0];
 
    if (shader_type != PIPE_SHADER_COMPUTE) {
       mach->Inputs = align_malloc(sizeof(struct tgsi_exec_vector) * PIPE_MAX_SHADER_INPUTS, 16);
@@ -1338,6 +1362,7 @@ tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach)
    if (mach) {
       FREE(mach->Instructions);
       FREE(mach->Declarations);
+      FREE(mach->Imms);
 
       align_free(mach->Inputs);
       align_free(mach->Outputs);
@@ -1454,6 +1479,17 @@ micro_pow(
 #endif
 }
 
+static void
+micro_ldexp(union tgsi_exec_channel *dst,
+            const union tgsi_exec_channel *src0,
+            const union tgsi_exec_channel *src1)
+{
+   dst->f[0] = ldexpf(src0->f[0], src1->i[0]);
+   dst->f[1] = ldexpf(src0->f[1], src1->i[1]);
+   dst->f[2] = ldexpf(src0->f[2], src1->i[2]);
+   dst->f[3] = ldexpf(src0->f[3], src1->i[3]);
+}
+
 static void
 micro_sub(union tgsi_exec_channel *dst,
           const union tgsi_exec_channel *src0,
@@ -1467,7 +1503,6 @@ micro_sub(union tgsi_exec_channel *dst,
 
 static void
 fetch_src_file_channel(const struct tgsi_exec_machine *mach,
-                       const uint chan_index,
                        const uint file,
                        const uint swizzle,
                        const union tgsi_exec_channel *index,
@@ -1559,15 +1594,6 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
       }
       break;
 
-   case TGSI_FILE_PREDICATE:
-      for (i = 0; i < TGSI_QUAD_SIZE; i++) {
-         assert(index->i[i] >= 0 && index->i[i] < TGSI_EXEC_NUM_PREDS);
-         assert(index2D->i[i] == 0);
-
-         chan->u[i] = mach->Predicates[0].xyzw[swizzle].u[i];
-      }
-      break;
-
    case TGSI_FILE_OUTPUT:
       /* vertex/fragment output vars can be read too */
       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
@@ -1587,14 +1613,11 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
 }
 
 static void
-fetch_source_d(const struct tgsi_exec_machine *mach,
-               union tgsi_exec_channel *chan,
-               const struct tgsi_full_src_register *reg,
-               const uint chan_index,
-               enum tgsi_exec_datatype src_datatype)
+get_index_registers(const struct tgsi_exec_machine *mach,
+                    const struct tgsi_full_src_register *reg,
+                    union tgsi_exec_channel *index,
+                    union tgsi_exec_channel *index2D)
 {
-   union tgsi_exec_channel index;
-   union tgsi_exec_channel index2D;
    uint swizzle;
 
    /* We start with a direct index into a register file.
@@ -1604,10 +1627,10 @@ fetch_source_d(const struct tgsi_exec_machine *mach,
     *       file = Register.File
     *       [1] = Register.Index
     */
-   index.i[0] =
-   index.i[1] =
-   index.i[2] =
-   index.i[3] = reg->Register.Index;
+   index->i[0] =
+   index->i[1] =
+   index->i[2] =
+   index->i[3] = reg->Register.Index;
 
    /* There is an extra source register that indirectly subscripts
     * a register file. The direct index now becomes an offset
@@ -1633,7 +1656,6 @@ fetch_source_d(const struct tgsi_exec_machine *mach,
       /* get current value of address register[swizzle] */
       swizzle = reg->Indirect.Swizzle;
       fetch_src_file_channel(mach,
-                             chan_index,
                              reg->Indirect.File,
                              swizzle,
                              &index2,
@@ -1641,17 +1663,17 @@ fetch_source_d(const struct tgsi_exec_machine *mach,
                              &indir_index);
 
       /* add value of address register to the offset */
-      index.i[0] += indir_index.i[0];
-      index.i[1] += indir_index.i[1];
-      index.i[2] += indir_index.i[2];
-      index.i[3] += indir_index.i[3];
+      index->i[0] += indir_index.i[0];
+      index->i[1] += indir_index.i[1];
+      index->i[2] += indir_index.i[2];
+      index->i[3] += indir_index.i[3];
 
       /* for disabled execution channels, zero-out the index to
        * avoid using a potential garbage value.
        */
       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
          if ((execmask & (1 << i)) == 0)
-            index.i[i] = 0;
+            index->i[i] = 0;
       }
    }
 
@@ -1664,10 +1686,10 @@ fetch_source_d(const struct tgsi_exec_machine *mach,
     *       [3] = Dimension.Index
     */
    if (reg->Register.Dimension) {
-      index2D.i[0] =
-      index2D.i[1] =
-      index2D.i[2] =
-      index2D.i[3] = reg->Dimension.Index;
+      index2D->i[0] =
+      index2D->i[1] =
+      index2D->i[2] =
+      index2D->i[3] = reg->Dimension.Index;
 
       /* Again, the second subscript index can be addressed indirectly
        * identically to the first one.
@@ -1693,24 +1715,23 @@ fetch_source_d(const struct tgsi_exec_machine *mach,
 
          swizzle = reg->DimIndirect.Swizzle;
          fetch_src_file_channel(mach,
-                                chan_index,
                                 reg->DimIndirect.File,
                                 swizzle,
                                 &index2,
                                 &ZeroVec,
                                 &indir_index);
 
-         index2D.i[0] += indir_index.i[0];
-         index2D.i[1] += indir_index.i[1];
-         index2D.i[2] += indir_index.i[2];
-         index2D.i[3] += indir_index.i[3];
+         index2D->i[0] += indir_index.i[0];
+         index2D->i[1] += indir_index.i[1];
+         index2D->i[2] += indir_index.i[2];
+         index2D->i[3] += indir_index.i[3];
 
          /* for disabled execution channels, zero-out the index to
           * avoid using a potential garbage value.
           */
          for (i = 0; i < TGSI_QUAD_SIZE; i++) {
             if ((execmask & (1 << i)) == 0) {
-               index2D.i[i] = 0;
+               index2D->i[i] = 0;
             }
          }
       }
@@ -1720,15 +1741,29 @@ fetch_source_d(const struct tgsi_exec_machine *mach,
        * by a dimension register and continue the saga.
        */
    } else {
-      index2D.i[0] =
-      index2D.i[1] =
-      index2D.i[2] =
-      index2D.i[3] = 0;
+      index2D->i[0] =
+      index2D->i[1] =
+      index2D->i[2] =
+      index2D->i[3] = 0;
    }
+}
+
+
+static void
+fetch_source_d(const struct tgsi_exec_machine *mach,
+               union tgsi_exec_channel *chan,
+               const struct tgsi_full_src_register *reg,
+              const uint chan_index)
+{
+   union tgsi_exec_channel index;
+   union tgsi_exec_channel index2D;
+   uint swizzle;
+
+   get_index_registers(mach, reg, &index, &index2D);
+
 
    swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index );
    fetch_src_file_channel(mach,
-                          chan_index,
                           reg->Register.File,
                           swizzle,
                           &index,
@@ -1743,7 +1778,7 @@ fetch_source(const struct tgsi_exec_machine *mach,
              const uint chan_index,
              enum tgsi_exec_datatype src_datatype)
 {
-   fetch_source_d(mach, chan, reg, chan_index, src_datatype);
+   fetch_source_d(mach, chan, reg, chan_index);
 
    if (reg->Register.Absolute) {
       if (src_datatype == TGSI_EXEC_DATA_FLOAT) {
@@ -1766,15 +1801,12 @@ static union tgsi_exec_channel *
 store_dest_dstret(struct tgsi_exec_machine *mach,
                  const union tgsi_exec_channel *chan,
                  const struct tgsi_full_dst_register *reg,
-                 const struct tgsi_full_instruction *inst,
                  uint chan_index,
                  enum tgsi_exec_datatype dst_datatype)
 {
-   uint i;
    static union tgsi_exec_channel null;
    union tgsi_exec_channel *dst;
    union tgsi_exec_channel index2D;
-   uint execmask = mach->ExecMask;
    int offset = 0;  /* indirection offset */
    int index;
 
@@ -1809,7 +1841,6 @@ store_dest_dstret(struct tgsi_exec_machine *mach,
 
       /* fetch values from the address/indirection register */
       fetch_src_file_channel(mach,
-                             chan_index,
                              reg->Indirect.File,
                              swizzle,
                              &index,
@@ -1859,7 +1890,6 @@ store_dest_dstret(struct tgsi_exec_machine *mach,
 
          swizzle = reg->DimIndirect.Swizzle;
          fetch_src_file_channel(mach,
-                                chan_index,
                                 reg->DimIndirect.File,
                                 swizzle,
                                 &index2,
@@ -1926,58 +1956,11 @@ store_dest_dstret(struct tgsi_exec_machine *mach,
       dst = &mach->Addrs[index].xyzw[chan_index];
       break;
 
-   case TGSI_FILE_PREDICATE:
-      index = reg->Register.Index;
-      assert(index < TGSI_EXEC_NUM_PREDS);
-      dst = &mach->Predicates[index].xyzw[chan_index];
-      break;
-
    default:
       assert( 0 );
       return NULL;
    }
 
-   if (inst->Instruction.Predicate) {
-      uint swizzle;
-      union tgsi_exec_channel *pred;
-
-      switch (chan_index) {
-      case TGSI_CHAN_X:
-         swizzle = inst->Predicate.SwizzleX;
-         break;
-      case TGSI_CHAN_Y:
-         swizzle = inst->Predicate.SwizzleY;
-         break;
-      case TGSI_CHAN_Z:
-         swizzle = inst->Predicate.SwizzleZ;
-         break;
-      case TGSI_CHAN_W:
-         swizzle = inst->Predicate.SwizzleW;
-         break;
-      default:
-         assert(0);
-         return NULL;
-      }
-
-      assert(inst->Predicate.Index == 0);
-
-      pred = &mach->Predicates[inst->Predicate.Index].xyzw[swizzle];
-
-      if (inst->Predicate.Negate) {
-         for (i = 0; i < TGSI_QUAD_SIZE; i++) {
-            if (pred->u[i]) {
-               execmask &= ~(1 << i);
-            }
-         }
-      } else {
-         for (i = 0; i < TGSI_QUAD_SIZE; i++) {
-            if (!pred->u[i]) {
-               execmask &= ~(1 << i);
-            }
-         }
-      }
-   }
-
    return dst;
 }
 
@@ -1985,7 +1968,6 @@ static void
 store_dest_double(struct tgsi_exec_machine *mach,
                  const union tgsi_exec_channel *chan,
                  const struct tgsi_full_dst_register *reg,
-                 const struct tgsi_full_instruction *inst,
                  uint chan_index,
                  enum tgsi_exec_datatype dst_datatype)
 {
@@ -1993,8 +1975,7 @@ store_dest_double(struct tgsi_exec_machine *mach,
    const uint execmask = mach->ExecMask;
    int i;
 
-   dst = store_dest_dstret(mach, chan, reg, inst, chan_index,
-                          dst_datatype);
+   dst = store_dest_dstret(mach, chan, reg, chan_index, dst_datatype);
    if (!dst)
       return;
 
@@ -2016,8 +1997,7 @@ store_dest(struct tgsi_exec_machine *mach,
    const uint execmask = mach->ExecMask;
    int i;
 
-   dst = store_dest_dstret(mach, chan, reg, inst, chan_index,
-                    dst_datatype);
+   dst = store_dest_dstret(mach, chan, reg, chan_index, dst_datatype);
    if (!dst)
       return;
 
@@ -2093,8 +2073,7 @@ exec_kill_if(struct tgsi_exec_machine *mach,
  * Unconditional fragment kill/discard.
  */
 static void
-exec_kill(struct tgsi_exec_machine *mach,
-          const struct tgsi_full_instruction *inst)
+exec_kill(struct tgsi_exec_machine *mach)
 {
    uint kilmask; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */
 
@@ -2104,35 +2083,52 @@ exec_kill(struct tgsi_exec_machine *mach,
 }
 
 static void
-emit_vertex(struct tgsi_exec_machine *mach)
+emit_vertex(struct tgsi_exec_machine *mach,
+            const struct tgsi_full_instruction *inst)
 {
+   union tgsi_exec_channel r[1];
+   unsigned stream_id;
+   unsigned *prim_count;
    /* FIXME: check for exec mask correctly
    unsigned i;
    for (i = 0; i < TGSI_QUAD_SIZE; ++i) {
          if ((mach->ExecMask & (1 << i)))
    */
+   IFETCH(&r[0], 0, TGSI_CHAN_X);
+   stream_id = r[0].u[0];
+   prim_count = &mach->Temps[temp_prim_idxs[stream_id].idx].xyzw[temp_prim_idxs[stream_id].chan].u[0];
    if (mach->ExecMask) {
-      if (mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]] >= mach->MaxOutputVertices)
+      if (mach->Primitives[stream_id][*prim_count] >= mach->MaxOutputVertices)
          return;
 
+      if (mach->Primitives[stream_id][*prim_count] == 0)
+         mach->PrimitiveOffsets[stream_id][*prim_count] = mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0];
       mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] += mach->NumOutputs;
-      mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]]++;
+      mach->Primitives[stream_id][*prim_count]++;
    }
 }
 
 static void
-emit_primitive(struct tgsi_exec_machine *mach)
+emit_primitive(struct tgsi_exec_machine *mach,
+               const struct tgsi_full_instruction *inst)
 {
-   unsigned *prim_count = &mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0];
+   unsigned *prim_count;
+   union tgsi_exec_channel r[1];
+   unsigned stream_id = 0;
    /* FIXME: check for exec mask correctly
    unsigned i;
    for (i = 0; i < TGSI_QUAD_SIZE; ++i) {
          if ((mach->ExecMask & (1 << i)))
    */
+   if (inst) {
+      IFETCH(&r[0], 0, TGSI_CHAN_X);
+      stream_id = r[0].u[0];
+   }
+   prim_count = &mach->Temps[temp_prim_idxs[stream_id].idx].xyzw[temp_prim_idxs[stream_id].chan].u[0];
    if (mach->ExecMask) {
       ++(*prim_count);
       debug_assert((*prim_count * mach->NumOutputs) < mach->MaxGeometryShaderOutputs);
-      mach->Primitives[*prim_count] = 0;
+      mach->Primitives[stream_id][*prim_count] = 0;
    }
 }
 
@@ -2141,9 +2137,9 @@ conditional_emit_primitive(struct tgsi_exec_machine *mach)
 {
    if (PIPE_SHADER_GEOMETRY == mach->ShaderType) {
       int emitted_verts =
-         mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]];
+         mach->Primitives[0][mach->Temps[temp_prim_idxs[0].idx].xyzw[temp_prim_idxs[0].chan].u[0]];
       if (emitted_verts) {
-         emit_primitive(mach);
+         emit_primitive(mach, NULL);
       }
    }
 }
@@ -2204,11 +2200,11 @@ fetch_texel_offsets(struct tgsi_exec_machine *mach,
       union tgsi_exec_channel index;
       union tgsi_exec_channel offset[3];
       index.i[0] = index.i[1] = index.i[2] = index.i[3] = inst->TexOffsets[0].Index;
-      fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
+      fetch_src_file_channel(mach, inst->TexOffsets[0].File,
                              inst->TexOffsets[0].SwizzleX, &index, &ZeroVec, &offset[0]);
-      fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
+      fetch_src_file_channel(mach, inst->TexOffsets[0].File,
                              inst->TexOffsets[0].SwizzleY, &index, &ZeroVec, &offset[1]);
-      fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
+      fetch_src_file_channel(mach, inst->TexOffsets[0].File,
                              inst->TexOffsets[0].SwizzleZ, &index, &ZeroVec, &offset[2]);
      offsets[0] = offset[0].i[0];
      offsets[1] = offset[1].i[0];
@@ -2261,7 +2257,6 @@ fetch_sampler_unit(struct tgsi_exec_machine *mach,
       index2.i[3] = reg->Indirect.Index;
 
       fetch_src_file_channel(mach,
-                             0,
                              reg->Indirect.File,
                              reg->Indirect.Swizzle,
                              &index2,
@@ -2312,7 +2307,7 @@ exec_tex(struct tgsi_exec_machine *mach,
 
    assert(dim <= 4);
    if (shadow_ref >= 0)
-      assert(shadow_ref >= dim && shadow_ref < ARRAY_SIZE(args));
+      assert(shadow_ref >= dim && shadow_ref < (int)ARRAY_SIZE(args));
 
    /* fetch modifier to the last argument */
    if (modifier != TEX_MODIFIER_NONE) {
@@ -2324,7 +2319,6 @@ exec_tex(struct tgsi_exec_machine *mach,
          FETCH(&r[last], 0, TGSI_CHAN_W);
       }
       else {
-         assert(shadow_ref != 4);
          FETCH(&r[last], 1, TGSI_CHAN_X);
       }
 
@@ -2348,7 +2342,7 @@ exec_tex(struct tgsi_exec_machine *mach,
          control = TGSI_SAMPLER_GATHER;
    }
    else {
-      for (i = dim; i < ARRAY_SIZE(args); i++)
+      for (i = dim; i < (int)ARRAY_SIZE(args); i++)
          args[i] = &ZeroVec;
    }
 
@@ -2399,15 +2393,22 @@ static void
 exec_lodq(struct tgsi_exec_machine *mach,
           const struct tgsi_full_instruction *inst)
 {
-   uint unit;
-   int dim;
-   int i;
+   uint resource_unit, sampler_unit;
+   unsigned dim;
+   unsigned i;
    union tgsi_exec_channel coords[4];
    const union tgsi_exec_channel *args[ARRAY_SIZE(coords)];
    union tgsi_exec_channel r[2];
 
-   unit = fetch_sampler_unit(mach, inst, 1);
-   dim = tgsi_util_get_texture_coord_dim(inst->Texture.Texture);
+   resource_unit = fetch_sampler_unit(mach, inst, 1);
+   if (inst->Instruction.Opcode == TGSI_OPCODE_LOD) {
+      uint target = mach->SamplerViews[resource_unit].Resource;
+      dim = tgsi_util_get_texture_coord_dim(target);
+      sampler_unit = fetch_sampler_unit(mach, inst, 2);
+   } else {
+      dim = tgsi_util_get_texture_coord_dim(inst->Texture.Texture);
+      sampler_unit = resource_unit;
+   }
    assert(dim <= ARRAY_SIZE(coords));
    /* fetch coordinates */
    for (i = 0; i < dim; i++) {
@@ -2417,7 +2418,7 @@ exec_lodq(struct tgsi_exec_machine *mach,
    for (i = dim; i < ARRAY_SIZE(coords); i++) {
       args[i] = &ZeroVec;
    }
-   mach->Sampler->query_lod(mach->Sampler, unit, unit,
+   mach->Sampler->query_lod(mach->Sampler, resource_unit, sampler_unit,
                             args[0]->f,
                             args[1]->f,
                             args[2]->f,
@@ -2434,6 +2435,35 @@ exec_lodq(struct tgsi_exec_machine *mach,
       store_dest(mach, &r[1], &inst->Dst[0], inst, TGSI_CHAN_Y,
                  TGSI_EXEC_DATA_FLOAT);
    }
+   if (inst->Instruction.Opcode == TGSI_OPCODE_LOD) {
+      unsigned char swizzles[4];
+      unsigned chan;
+      swizzles[0] = inst->Src[1].Register.SwizzleX;
+      swizzles[1] = inst->Src[1].Register.SwizzleY;
+      swizzles[2] = inst->Src[1].Register.SwizzleZ;
+      swizzles[3] = inst->Src[1].Register.SwizzleW;
+
+      for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
+         if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+            if (swizzles[chan] >= 2) {
+               store_dest(mach, &ZeroVec,
+                          &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+            } else {
+               store_dest(mach, &r[swizzles[chan]],
+                          &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+            }
+         }
+      }
+   } else {
+      if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
+         store_dest(mach, &r[0], &inst->Dst[0], inst, TGSI_CHAN_X,
+                    TGSI_EXEC_DATA_FLOAT);
+      }
+      if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
+         store_dest(mach, &r[1], &inst->Dst[0], inst, TGSI_CHAN_Y,
+                    TGSI_EXEC_DATA_FLOAT);
+      }
+   }
 }
 
 static void
@@ -2690,6 +2720,9 @@ exec_sample(struct tgsi_exec_machine *mach,
          lod = &c1;
          control = TGSI_SAMPLER_LOD_EXPLICIT;
       }
+      else if (modifier == TEX_MODIFIER_GATHER) {
+         control = TGSI_SAMPLER_GATHER;
+      }
       else {
          assert(modifier == TEX_MODIFIER_LEVEL_ZERO);
          control = TGSI_SAMPLER_LOD_ZERO;
@@ -3243,60 +3276,6 @@ exec_dp4(struct tgsi_exec_machine *mach,
    }
 }
 
-static void
-exec_dp2a(struct tgsi_exec_machine *mach,
-          const struct tgsi_full_instruction *inst)
-{
-   unsigned int chan;
-   union tgsi_exec_channel arg[3];
-
-   fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-   fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-   micro_mul(&arg[2], &arg[0], &arg[1]);
-
-   fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
-   fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
-   micro_mad(&arg[0], &arg[0], &arg[1], &arg[2]);
-
-   fetch_source(mach, &arg[1], &inst->Src[2], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-   micro_add(&arg[0], &arg[0], &arg[1]);
-
-   for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
-      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
-         store_dest(mach, &arg[0], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
-      }
-   }
-}
-
-static void
-exec_dph(struct tgsi_exec_machine *mach,
-         const struct tgsi_full_instruction *inst)
-{
-   unsigned int chan;
-   union tgsi_exec_channel arg[3];
-
-   fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-   fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-   micro_mul(&arg[2], &arg[0], &arg[1]);
-
-   fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
-   fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
-   micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]);
-
-   fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
-   fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
-   micro_mad(&arg[0], &arg[0], &arg[1], &arg[2]);
-
-   fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
-   micro_add(&arg[0], &arg[0], &arg[1]);
-
-   for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
-      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
-         store_dest(mach, &arg[0], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
-      }
-   }
-}
-
 static void
 exec_dp2(struct tgsi_exec_machine *mach,
          const struct tgsi_full_instruction *inst)
@@ -3398,78 +3377,6 @@ exec_ucmp(struct tgsi_exec_machine *mach,
    }
 }
 
-static void
-exec_scs(struct tgsi_exec_machine *mach,
-         const struct tgsi_full_instruction *inst)
-{
-   if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY) {
-      union tgsi_exec_channel arg;
-      union tgsi_exec_channel result;
-
-      fetch_source(mach, &arg, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-
-      if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
-         micro_cos(&result, &arg);
-         store_dest(mach, &result, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-      }
-      if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
-         micro_sin(&result, &arg);
-         store_dest(mach, &result, &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
-      }
-   }
-   if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
-      store_dest(mach, &ZeroVec, &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
-   }
-   if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
-      store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
-   }
-}
-
-static void
-exec_xpd(struct tgsi_exec_machine *mach,
-         const struct tgsi_full_instruction *inst)
-{
-   union tgsi_exec_channel r[6];
-   union tgsi_exec_channel d[3];
-
-   fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
-   fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
-
-   micro_mul(&r[2], &r[0], &r[1]);
-
-   fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
-   fetch_source(mach, &r[4], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
-
-   micro_mul(&r[5], &r[3], &r[4] );
-   micro_sub(&d[TGSI_CHAN_X], &r[2], &r[5]);
-
-   fetch_source(mach, &r[2], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-
-   micro_mul(&r[3], &r[3], &r[2]);
-
-   fetch_source(mach, &r[5], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-
-   micro_mul(&r[1], &r[1], &r[5]);
-   micro_sub(&d[TGSI_CHAN_Y], &r[3], &r[1]);
-
-   micro_mul(&r[5], &r[5], &r[4]);
-   micro_mul(&r[0], &r[0], &r[2]);
-   micro_sub(&d[TGSI_CHAN_Z], &r[5], &r[0]);
-
-   if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
-      store_dest(mach, &d[TGSI_CHAN_X], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
-   }
-   if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
-      store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
-   }
-   if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
-      store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
-   }
-   if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
-      store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
-   }
-}
-
 static void
 exec_dst(struct tgsi_exec_machine *mach,
          const struct tgsi_full_instruction *inst)
@@ -3696,8 +3603,8 @@ fetch_double_channel(struct tgsi_exec_machine *mach,
    union tgsi_exec_channel src[2];
    uint i;
 
-   fetch_source_d(mach, &src[0], reg, chan_0, TGSI_EXEC_DATA_UINT);
-   fetch_source_d(mach, &src[1], reg, chan_1, TGSI_EXEC_DATA_UINT);
+   fetch_source_d(mach, &src[0], reg, chan_0);
+   fetch_source_d(mach, &src[1], reg, chan_1);
 
    for (i = 0; i < TGSI_QUAD_SIZE; i++) {
       chan->u[i][0] = src[0].u[i];
@@ -3746,9 +3653,9 @@ store_double_channel(struct tgsi_exec_machine *mach,
          }
    }
 
-   store_dest_double(mach, &dst[0], reg, inst, chan_0, TGSI_EXEC_DATA_UINT);
-   if (chan_1 != -1)
-      store_dest_double(mach, &dst[1], reg, inst, chan_1, TGSI_EXEC_DATA_UINT);
+   store_dest_double(mach, &dst[0], reg, chan_0, TGSI_EXEC_DATA_UINT);
+   if (chan_1 != (unsigned)-1)
+      store_dest_double(mach, &dst[1], reg, chan_1, TGSI_EXEC_DATA_UINT);
 }
 
 static void
@@ -3870,17 +3777,15 @@ exec_dfracexp(struct tgsi_exec_machine *mach,
    union tgsi_double_channel dst;
    union tgsi_exec_channel dst_exp;
 
-   if (((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY) == TGSI_WRITEMASK_XY)) {
-      fetch_double_channel(mach, &src, &inst->Src[0], TGSI_CHAN_X, TGSI_CHAN_Y);
-      micro_dfracexp(&dst, &dst_exp, &src);
+   fetch_double_channel(mach, &src, &inst->Src[0], TGSI_CHAN_X, TGSI_CHAN_Y);
+   micro_dfracexp(&dst, &dst_exp, &src);
+   if ((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY) == TGSI_WRITEMASK_XY)
       store_double_channel(mach, &dst, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_CHAN_Y);
-      store_dest(mach, &dst_exp, &inst->Dst[1], inst, ffs(inst->Dst[1].Register.WriteMask) - 1, TGSI_EXEC_DATA_INT);
-   }
-   if (((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_ZW) == TGSI_WRITEMASK_ZW)) {
-      fetch_double_channel(mach, &src, &inst->Src[0], TGSI_CHAN_Z, TGSI_CHAN_W);
-      micro_dfracexp(&dst, &dst_exp, &src);
+   if ((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_ZW) == TGSI_WRITEMASK_ZW)
       store_double_channel(mach, &dst, &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_CHAN_W);
-      store_dest(mach, &dst_exp, &inst->Dst[1], inst, ffs(inst->Dst[1].Register.WriteMask) - 1, TGSI_EXEC_DATA_INT);
+   for (unsigned chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
+      if (inst->Dst[1].Register.WriteMask & (1 << chan))
+         store_dest(mach, &dst_exp, &inst->Dst[1], inst, chan, TGSI_EXEC_DATA_INT);
    }
 }
 
@@ -4082,6 +3987,38 @@ exec_load(struct tgsi_exec_machine *mach,
       exec_load_mem(mach, inst);
 }
 
+static uint
+fetch_store_img_unit(struct tgsi_exec_machine *mach,
+                     const struct tgsi_full_dst_register *dst)
+{
+   uint unit = 0;
+   int i;
+   if (dst->Register.Indirect) {
+      union tgsi_exec_channel indir_index, index2;
+      const uint execmask = mach->ExecMask;
+      index2.i[0] =
+      index2.i[1] =
+      index2.i[2] =
+      index2.i[3] = dst->Indirect.Index;
+
+      fetch_src_file_channel(mach,
+                             dst->Indirect.File,
+                             dst->Indirect.Swizzle,
+                             &index2,
+                             &ZeroVec,
+                             &indir_index);
+      for (i = 0; i < TGSI_QUAD_SIZE; i++) {
+         if (execmask & (1 << i)) {
+            unit = dst->Register.Index + indir_index.i[i];
+            break;
+         }
+      }
+   } else {
+      unit = dst->Register.Index;
+   }
+   return unit;
+}
+
 static void
 exec_store_img(struct tgsi_exec_machine *mach,
                const struct tgsi_full_instruction *inst)
@@ -4095,7 +4032,7 @@ exec_store_img(struct tgsi_exec_machine *mach,
    int i, j;
    uint unit;
    int kilmask = mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
-   unit = inst->Dst[0].Register.Index;
+   unit = fetch_store_img_unit(mach, &inst->Dst[0]);
    dim = get_image_coord_dim(inst->Memory.Texture);
    sample = get_image_coord_sample(inst->Memory.Texture);
    assert(dim <= 3);
@@ -4139,7 +4076,7 @@ exec_store_buf(struct tgsi_exec_machine *mach,
    uint unit;
    int kilmask = mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
 
-   unit = inst->Dst[0].Register.Index;
+   unit = fetch_store_img_unit(mach, &inst->Dst[0]);
 
    params.execmask = mach->ExecMask & mach->NonHelperMask & ~kilmask;
    params.unit = unit;
@@ -4392,6 +4329,9 @@ exec_atomop_mem(struct tgsi_exec_machine *mach,
       if (val == value[0].u[0])
          val = value2[0].u[0];
       break;
+   case TGSI_OPCODE_ATOMFADD:
+      val = fui(r[0].f[0] + value[0].f[0]);
+      break;
    default:
       break;
    }
@@ -4712,10 +4652,10 @@ micro_mod(union tgsi_exec_channel *dst,
           const union tgsi_exec_channel *src0,
           const union tgsi_exec_channel *src1)
 {
-   dst->i[0] = src0->i[0] % src1->i[0];
-   dst->i[1] = src0->i[1] % src1->i[1];
-   dst->i[2] = src0->i[2] % src1->i[2];
-   dst->i[3] = src0->i[3] % src1->i[3];
+   dst->i[0] = src1->i[0] ? src0->i[0] % src1->i[0] : ~0;
+   dst->i[1] = src1->i[1] ? src0->i[1] % src1->i[1] : ~0;
+   dst->i[2] = src1->i[2] ? src0->i[2] % src1->i[2] : ~0;
+   dst->i[3] = src1->i[3] ? src0->i[3] % src1->i[3] : ~0;
 }
 
 static void
@@ -5048,8 +4988,13 @@ micro_ibfe(union tgsi_exec_channel *dst,
 {
    int i;
    for (i = 0; i < 4; i++) {
-      int width = src2->i[i] & 0x1f;
+      int width = src2->i[i];
       int offset = src1->i[i] & 0x1f;
+      if (width == 32 && offset == 0) {
+         dst->i[i] = src0->i[i];
+         continue;
+      }
+      width &= 0x1f;
       if (width == 0)
          dst->i[i] = 0;
       else if (width + offset < 32)
@@ -5070,8 +5015,13 @@ micro_ubfe(union tgsi_exec_channel *dst,
 {
    int i;
    for (i = 0; i < 4; i++) {
-      int width = src2->u[i] & 0x1f;
+      int width = src2->u[i];
       int offset = src1->u[i] & 0x1f;
+      if (width == 32 && offset == 0) {
+         dst->u[i] = src0->u[i];
+         continue;
+      }
+      width &= 0x1f;
       if (width == 0)
          dst->u[i] = 0;
       else if (width + offset < 32)
@@ -5093,10 +5043,14 @@ micro_bfi(union tgsi_exec_channel *dst,
 {
    int i;
    for (i = 0; i < 4; i++) {
-      int width = src3->u[i] & 0x1f;
+      int width = src3->u[i];
       int offset = src2->u[i] & 0x1f;
-      int bitmask = ((1 << width) - 1) << offset;
-      dst->u[i] = ((src1->u[i] << offset) & bitmask) | (src0->u[i] & ~bitmask);
+      if (width == 32) {
+         dst->u[i] = src1->u[i];
+      } else {
+         int bitmask = ((1 << width) - 1) << offset;
+         dst->u[i] = ((src1->u[i] << offset) & bitmask) | (src0->u[i] & ~bitmask);
+      }
    }
 }
 
@@ -5242,10 +5196,6 @@ exec_instruction(
       exec_scalar_unary(mach, inst, micro_sqrt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
       break;
 
-   case TGSI_OPCODE_DP2A:
-      exec_dp2a(mach, inst);
-      break;
-
    case TGSI_OPCODE_FRC:
       exec_vector_unary(mach, inst, micro_frc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
       break;
@@ -5270,12 +5220,8 @@ exec_instruction(
       exec_scalar_binary(mach, inst, micro_pow, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
       break;
 
-   case TGSI_OPCODE_XPD:
-      exec_xpd(mach, inst);
-      break;
-
-   case TGSI_OPCODE_DPH:
-      exec_dph(mach, inst);
+   case TGSI_OPCODE_LDEXP:
+      exec_vector_binary(mach, inst, micro_ldexp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
       break;
 
    case TGSI_OPCODE_COS:
@@ -5291,7 +5237,7 @@ exec_instruction(
       break;
 
    case TGSI_OPCODE_KILL:
-      exec_kill (mach, inst);
+      exec_kill (mach);
       break;
 
    case TGSI_OPCODE_KILL_IF:
@@ -5504,10 +5450,6 @@ exec_instruction(
       exec_vector_trinary(mach, inst, micro_cmp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
       break;
 
-   case TGSI_OPCODE_SCS:
-      exec_scs(mach, inst);
-      break;
-
    case TGSI_OPCODE_DIV:
       exec_vector_binary(mach, inst, micro_div, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
       break;
@@ -5587,14 +5529,6 @@ exec_instruction(
       *pc = -1;
       break;
 
-   case TGSI_OPCODE_PUSHA:
-      assert (0);
-      break;
-
-   case TGSI_OPCODE_POPA:
-      assert (0);
-      break;
-
    case TGSI_OPCODE_CEIL:
       exec_vector_unary(mach, inst, micro_ceil, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
       break;
@@ -5631,10 +5565,6 @@ exec_instruction(
       exec_vector_binary(mach, inst, micro_xor, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
       break;
 
-   case TGSI_OPCODE_SAD:
-      assert (0);
-      break;
-
    case TGSI_OPCODE_TXF:
       exec_txf(mach, inst);
       break;
@@ -5644,11 +5574,11 @@ exec_instruction(
       break;
 
    case TGSI_OPCODE_EMIT:
-      emit_vertex(mach);
+      emit_vertex(mach, inst);
       break;
 
    case TGSI_OPCODE_ENDPRIM:
-      emit_primitive(mach);
+      emit_primitive(mach, inst);
       break;
 
    case TGSI_OPCODE_BGNLOOP:
@@ -5739,25 +5669,6 @@ exec_instruction(
    case TGSI_OPCODE_NOP:
       break;
 
-   case TGSI_OPCODE_BREAKC:
-      IFETCH(&r[0], 0, TGSI_CHAN_X);
-      /* update CondMask */
-      if (r[0].u[0] && (mach->ExecMask & 0x1)) {
-         mach->LoopMask &= ~0x1;
-      }
-      if (r[0].u[1] && (mach->ExecMask & 0x2)) {
-         mach->LoopMask &= ~0x2;
-      }
-      if (r[0].u[2] && (mach->ExecMask & 0x4)) {
-         mach->LoopMask &= ~0x4;
-      }
-      if (r[0].u[3] && (mach->ExecMask & 0x8)) {
-         mach->LoopMask &= ~0x8;
-      }
-      /* Todo: if mach->LoopMask == 0, jump to end of loop */
-      UPDATE_EXEC_MASK(mach);
-      break;
-
    case TGSI_OPCODE_F2I:
       exec_vector_unary(mach, inst, micro_f2i, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT);
       break;
@@ -5919,7 +5830,7 @@ exec_instruction(
       break;
 
    case TGSI_OPCODE_GATHER4:
-      assert(0);
+      exec_sample(mach, inst, TEX_MODIFIER_GATHER, FALSE);
       break;
 
    case TGSI_OPCODE_SVIEWINFO:
@@ -5934,6 +5845,10 @@ exec_instruction(
       assert(0);
       break;
 
+   case TGSI_OPCODE_LOD:
+      exec_lodq(mach, inst);
+      break;
+
    case TGSI_OPCODE_UARL:
       exec_vector_unary(mach, inst, micro_uarl, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_UINT);
       break;
@@ -6111,6 +6026,7 @@ exec_instruction(
    case TGSI_OPCODE_ATOMUMAX:
    case TGSI_OPCODE_ATOMIMIN:
    case TGSI_OPCODE_ATOMIMAX:
+   case TGSI_OPCODE_ATOMFADD:
       exec_atomop(mach, inst);
       break;
 
@@ -6248,8 +6164,10 @@ tgsi_exec_machine_setup_masks(struct tgsi_exec_machine *mach)
    mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] = 0;
 
    if (mach->ShaderType == PIPE_SHADER_GEOMETRY) {
-      mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0] = 0;
-      mach->Primitives[0] = 0;
+      for (unsigned i = 0; i < TGSI_MAX_VERTEX_STREAMS; i++) {
+         mach->Temps[temp_prim_idxs[i].idx].xyzw[temp_prim_idxs[i].chan].u[0] = 0;
+         mach->Primitives[i][0] = 0;
+      }
       /* GS runs on a single primitive for now */
       default_mask = 0x1;
    }