Example #1
0
/** Return number of src args for given instruction */
GLuint brw_wm_nr_args( GLuint opcode )
{
   switch (opcode) {
   case WM_FRONTFACING:
   case WM_PIXELXY:
      return 0;
   case WM_CINTERP:
   case WM_WPOSXY:
   case WM_DELTAXY:
      return 1;
   case WM_LINTERP:
   case WM_PIXELW:
      return 2;
   case WM_FB_WRITE:
   case WM_PINTERP:
      return 3;
   case TGSI_OPCODE_TEX:
   case TGSI_OPCODE_TXP:
   case TGSI_OPCODE_TXB:
   case TGSI_OPCODE_TXD:
      /* sampler arg is held as a field in the instruction, not in an
       * actual register:
       */
      return tgsi_get_opcode_info(opcode)->num_src - 1;

   default:
      assert(opcode < MAX_OPCODE);
      return tgsi_get_opcode_info(opcode)->num_src;
   }
}
Example #2
0
static void print_opcode( unsigned opcode )
{
   switch (opcode) {
   case WM_PIXELXY:
      debug_printf("PIXELXY");
      break;
   case WM_DELTAXY:
      debug_printf("DELTAXY");
      break;
   case WM_PIXELW:
      debug_printf("PIXELW");
      break;
   case WM_WPOSXY:
      debug_printf("WPOSXY");
      break;
   case WM_PINTERP:
      debug_printf("PINTERP");
      break;
   case WM_LINTERP:
      debug_printf("LINTERP");
      break;
   case WM_CINTERP:
      debug_printf("CINTERP");
      break;
   case WM_FB_WRITE:
      debug_printf("FB_WRITE");
      break;
   case WM_FRONTFACING:
      debug_printf("FRONTFACING");
      break;
   default:
      debug_printf("%s", tgsi_get_opcode_info(opcode)->mnemonic);
      break;
   }
}
Example #3
0
/**
 * Is the opcode a "true" texture instruction which samples from a
 * texture map?
 */
static bool
is_texture_inst(unsigned opcode)
{
   return (opcode != TGSI_OPCODE_TXQ &&
           opcode != TGSI_OPCODE_TXQS &&
           opcode != TGSI_OPCODE_TXQ_LZ &&
           opcode != TGSI_OPCODE_LODQ &&
           tgsi_get_opcode_info(opcode)->is_tex);
}
Example #4
0
static void validate( unsigned opcode,
                      unsigned nr_dst,
                      unsigned nr_src )
{
#ifdef DEBUG
   const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
   assert(info);
   if(info) {
      assert(nr_dst == info->num_dst);
      assert(nr_src == info->num_src);
   }
#endif
}
Example #5
0
static boolean
iter_instruction(
   struct tgsi_iterate_context *iter,
   struct tgsi_full_instruction *inst )
{
   struct dump_ctx *ctx = (struct dump_ctx *) iter;
   uint instno = ctx->instno++;
   const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
   uint i;
   boolean first_reg = TRUE;

   INSTID( instno );
   TXT( ": " );

   ctx->indent -= info->pre_dedent;
   for(i = 0; (int)i < ctx->indent; ++i)
      TXT( "  " );
   ctx->indent += info->post_indent;

   if (inst->Instruction.Predicate) {
      CHR( '(' );

      if (inst->Predicate.Negate)
         CHR( '!' );

      TXT( "PRED[" );
      SID( inst->Predicate.Index );
      CHR( ']' );

      if (inst->Predicate.SwizzleX != TGSI_SWIZZLE_X ||
          inst->Predicate.SwizzleY != TGSI_SWIZZLE_Y ||
          inst->Predicate.SwizzleZ != TGSI_SWIZZLE_Z ||
          inst->Predicate.SwizzleW != TGSI_SWIZZLE_W) {
         CHR( '.' );
         ENM( inst->Predicate.SwizzleX, tgsi_swizzle_names );
         ENM( inst->Predicate.SwizzleY, tgsi_swizzle_names );
         ENM( inst->Predicate.SwizzleZ, tgsi_swizzle_names );
         ENM( inst->Predicate.SwizzleW, tgsi_swizzle_names );
      }

      TXT( ") " );
   }

   TXT( info->mnemonic );

   switch (inst->Instruction.Saturate) {
   case TGSI_SAT_NONE:
      break;
   case TGSI_SAT_ZERO_ONE:
      TXT( "_SAT" );
      break;
   case TGSI_SAT_MINUS_PLUS_ONE:
      TXT( "_SATNV" );
      break;
   default:
      assert( 0 );
   }

   for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
      const struct tgsi_full_dst_register *dst = &inst->Dst[i];

      if (!first_reg)
         CHR( ',' );
      CHR( ' ' );

      _dump_register_dst( ctx, dst );
      _dump_writemask( ctx, dst->Register.WriteMask );

      first_reg = FALSE;
   }

   for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
      const struct tgsi_full_src_register *src = &inst->Src[i];

      if (!first_reg)
         CHR( ',' );
      CHR( ' ' );

      if (src->Register.Negate)
         CHR( '-' );
      if (src->Register.Absolute)
         CHR( '|' );

      _dump_register_src(ctx, src);

      if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
          src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
          src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
          src->Register.SwizzleW != TGSI_SWIZZLE_W) {
         CHR( '.' );
         ENM( src->Register.SwizzleX, tgsi_swizzle_names );
         ENM( src->Register.SwizzleY, tgsi_swizzle_names );
         ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
         ENM( src->Register.SwizzleW, tgsi_swizzle_names );
      }

      if (src->Register.Absolute)
         CHR( '|' );

      first_reg = FALSE;
   }

   if (inst->Instruction.Texture) {
      TXT( ", " );
      ENM( inst->Texture.Texture, tgsi_texture_names );
      for (i = 0; i < inst->Texture.NumOffsets; i++) {
         TXT( ", " );
         ENM( inst->TexOffsets[i].File, tgsi_file_names);
         CHR( '[' );
         SID( inst->TexOffsets[i].Index );
         CHR( ']' );
         CHR( '.' );
         ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
         ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
         ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
      }
   }

   switch (inst->Instruction.Opcode) {
   case TGSI_OPCODE_IF:
   case TGSI_OPCODE_UIF:
   case TGSI_OPCODE_ELSE:
   case TGSI_OPCODE_BGNLOOP:
   case TGSI_OPCODE_ENDLOOP:
   case TGSI_OPCODE_CAL:
      TXT( " :" );
      UID( inst->Label.Label );
      break;
   }

   /* update indentation */
   if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
       inst->Instruction.Opcode == TGSI_OPCODE_UIF ||
       inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
       inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
      ctx->indentation += indent_spaces;
   }

   EOL();

   return TRUE;
}
Example #6
0
static boolean
parse_instruction(
   struct translate_ctx *ctx,
   boolean has_label )
{
   uint i;
   uint saturate = 0;
   const struct tgsi_opcode_info *info;
   struct tgsi_full_instruction inst;
   const char *cur;
   uint advance;

   inst = tgsi_default_full_instruction();

   /* Parse predicate.
    */
   eat_opt_white( &ctx->cur );
   if (*ctx->cur == '(') {
      uint file;
      int index;
      uint swizzle[4];
      boolean parsed_swizzle;

      inst.Instruction.Predicate = 1;

      ctx->cur++;
      if (*ctx->cur == '!') {
         ctx->cur++;
         inst.Predicate.Negate = 1;
      }

      if (!parse_register_1d( ctx, &file, &index ))
         return FALSE;

      if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
         if (parsed_swizzle) {
            inst.Predicate.SwizzleX = swizzle[0];
            inst.Predicate.SwizzleY = swizzle[1];
            inst.Predicate.SwizzleZ = swizzle[2];
            inst.Predicate.SwizzleW = swizzle[3];
         }
      }

      if (*ctx->cur != ')') {
         report_error( ctx, "Expected `)'" );
         return FALSE;
      }

      ctx->cur++;
   }

   /* Parse instruction name.
    */
   eat_opt_white( &ctx->cur );
   for (i = 0; i < TGSI_OPCODE_LAST; i++) {
      cur = ctx->cur;

      info = tgsi_get_opcode_info( i );
      if (match_inst(&cur, &saturate, info)) {
         if (info->num_dst + info->num_src + info->is_tex == 0) {
            ctx->cur = cur;
            break;
         }
         else if (*cur == '\0' || eat_white( &cur )) {
            ctx->cur = cur;
            break;
         }
      }
   }
   if (i == TGSI_OPCODE_LAST) {
      if (has_label)
         report_error( ctx, "Unknown opcode" );
      else
         report_error( ctx, "Expected `DCL', `IMM' or a label" );
      return FALSE;
   }

   inst.Instruction.Opcode = i;
   inst.Instruction.Saturate = saturate;
   inst.Instruction.NumDstRegs = info->num_dst;
   inst.Instruction.NumSrcRegs = info->num_src;

   if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
      /*
       * These are not considered tex opcodes here (no additional
       * target argument) however we're required to set the Texture
       * bit so we can set the number of tex offsets.
       */
      inst.Instruction.Texture = 1;
      inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
   }

   if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) ||
       i == TGSI_OPCODE_RESQ) {
      inst.Instruction.Memory = 1;
      inst.Memory.Qualifier = 0;
   }

   /* Parse instruction operands.
    */
   for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
      if (i > 0) {
         eat_opt_white( &ctx->cur );
         if (*ctx->cur != ',') {
            report_error( ctx, "Expected `,'" );
            return FALSE;
         }
         ctx->cur++;
         eat_opt_white( &ctx->cur );
      }

      if (i < info->num_dst) {
         if (!parse_dst_operand( ctx, &inst.Dst[i] ))
            return FALSE;
      }
      else if (i < info->num_dst + info->num_src) {
         if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
            return FALSE;
      }
      else {
         uint j;

         for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
            if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
               inst.Instruction.Texture = 1;
               inst.Texture.Texture = j;
               break;
            }
         }
         if (j == TGSI_TEXTURE_COUNT) {
            report_error( ctx, "Expected texture target" );
            return FALSE;
         }
      }
   }

   cur = ctx->cur;
   eat_opt_white( &cur );
   for (i = 0; inst.Instruction.Texture && *cur == ','; i++) {
         cur++;
         eat_opt_white( &cur );
         ctx->cur = cur;
         if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] ))
            return FALSE;
         cur = ctx->cur;
         eat_opt_white( &cur );
   }
   inst.Texture.NumOffsets = i;

   cur = ctx->cur;
   eat_opt_white(&cur);
   for (i = 0; inst.Instruction.Memory && *cur == ','; i++) {
      uint j;
      cur++;
      eat_opt_white(&cur);
      ctx->cur = cur;
      for (j = 0; j < 3; j++) {
         if (str_match_nocase_whole(&ctx->cur, tgsi_memory_names[j])) {
            inst.Memory.Qualifier |= 1U << j;
            break;
         }
      }
      if (j == 3) {
         report_error(ctx, "Expected memory qualifier");
         return FALSE;
      }
      cur = ctx->cur;
      eat_opt_white(&cur);
   }

   cur = ctx->cur;
   eat_opt_white( &cur );
   if (info->is_branch && *cur == ':') {
      uint target;

      cur++;
      eat_opt_white( &cur );
      if (!parse_uint( &cur, &target )) {
         report_error( ctx, "Expected a label" );
         return FALSE;
      }
      inst.Instruction.Label = 1;
      inst.Label.Label = target;
      ctx->cur = cur;
   }

   advance = tgsi_build_full_instruction(
      &inst,
      ctx->tokens_cur,
      ctx->header,
      (uint) (ctx->tokens_end - ctx->tokens_cur) );
   if (advance == 0)
      return FALSE;
   ctx->tokens_cur += advance;

   return TRUE;
}
void
lp_build_tgsi_aos(struct gallivm_state *gallivm,
                  const struct tgsi_token *tokens,
                  struct lp_type type,
                  const unsigned char swizzles[4],
                  LLVMValueRef consts_ptr,
                  const LLVMValueRef *inputs,
                  LLVMValueRef *outputs,
                  struct lp_build_sampler_aos *sampler,
                  const struct tgsi_shader_info *info)
{
   struct lp_build_tgsi_aos_context bld;
   struct tgsi_parse_context parse;
   uint num_immediates = 0;
   unsigned chan;
   int pc = 0;

   /* Setup build context */
   memset(&bld, 0, sizeof bld);
   lp_build_context_init(&bld.bld_base.base, gallivm, type);
   lp_build_context_init(&bld.bld_base.uint_bld, gallivm, lp_uint_type(type));
   lp_build_context_init(&bld.bld_base.int_bld, gallivm, lp_int_type(type));
   lp_build_context_init(&bld.int_bld, gallivm, lp_int_type(type));

   for (chan = 0; chan < 4; ++chan) {
      bld.swizzles[chan] = swizzles[chan];
      bld.inv_swizzles[swizzles[chan]] = chan;
   }

   bld.inputs = inputs;
   bld.outputs = outputs;
   bld.consts_ptr = consts_ptr;
   bld.sampler = sampler;
   bld.indirect_files = info->indirect_files;
   bld.bld_base.emit_swizzle = swizzle_aos;
   bld.bld_base.info = info;

   bld.bld_base.emit_fetch_funcs[TGSI_FILE_CONSTANT] = emit_fetch_constant;
   bld.bld_base.emit_fetch_funcs[TGSI_FILE_IMMEDIATE] = emit_fetch_immediate;
   bld.bld_base.emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_input;
   bld.bld_base.emit_fetch_funcs[TGSI_FILE_TEMPORARY] = emit_fetch_temporary;

   /* Set opcode actions */
   lp_set_default_actions_cpu(&bld.bld_base);

   if (!lp_bld_tgsi_list_init(&bld.bld_base)) {
      return;
   }

   tgsi_parse_init(&parse, tokens);

   while (!tgsi_parse_end_of_tokens(&parse)) {
      tgsi_parse_token(&parse);

      switch(parse.FullToken.Token.Type) {
      case TGSI_TOKEN_TYPE_DECLARATION:
         /* Inputs already interpolated */
         lp_emit_declaration_aos(&bld, &parse.FullToken.FullDeclaration);
         break;

      case TGSI_TOKEN_TYPE_INSTRUCTION:
         /* save expanded instruction */
         lp_bld_tgsi_add_instruction(&bld.bld_base,
                                     &parse.FullToken.FullInstruction);
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
         /* simply copy the immediate values into the next immediates[] slot */
         {
            const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
            float imm[4];
            assert(size <= 4);
            assert(num_immediates < LP_MAX_TGSI_IMMEDIATES);
            for (chan = 0; chan < 4; ++chan) {
               imm[chan] = 0.0f;
            }
            for (chan = 0; chan < size; ++chan) {
               unsigned swizzle = bld.swizzles[chan];
               imm[swizzle] = parse.FullToken.FullImmediate.u[chan].Float;
            }
            bld.immediates[num_immediates] =
                     lp_build_const_aos(gallivm, type,
                                        imm[0], imm[1], imm[2], imm[3],
                                        NULL);
            num_immediates++;
         }
         break;

      case TGSI_TOKEN_TYPE_PROPERTY:
         break;

      default:
         assert(0);
      }
   }

   while (pc != -1) {
      struct tgsi_full_instruction *instr = bld.bld_base.instructions + pc;
      const struct tgsi_opcode_info *opcode_info =
         tgsi_get_opcode_info(instr->Instruction.Opcode);
      if (!lp_emit_instruction_aos(&bld, instr, opcode_info, &pc))
         _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
                       opcode_info->mnemonic);
   }

   if (0) {
      LLVMBasicBlockRef block = LLVMGetInsertBlock(gallivm->builder);
      LLVMValueRef function = LLVMGetBasicBlockParent(block);
      debug_printf("11111111111111111111111111111 \n");
      tgsi_dump(tokens, 0);
      lp_debug_dump_value(function);
      debug_printf("2222222222222222222222222222 \n");
   }
   tgsi_parse_free(&parse);
   FREE(bld.bld_base.instructions);

   if (0) {
      LLVMModuleRef module = LLVMGetGlobalParent(
         LLVMGetBasicBlockParent(LLVMGetInsertBlock(gallivm->builder)));
      LLVMDumpModule(module);
   }

}
Example #8
0
const char *
tgsi_get_opcode_name( uint opcode )
{
   const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode);
   return info->mnemonic;
}
Example #9
0
static void
dump_instruction_verbose(
   struct tgsi_full_instruction  *inst,
   unsigned                      ignored,
   unsigned                      deflt,
   struct tgsi_full_instruction  *fi )
{
   unsigned i;

   TXT( "\nOpcode     : OPCODE_" );
   TXT( tgsi_get_opcode_info( inst->Instruction.Opcode )->mnemonic );
   if( deflt || fi->Instruction.Saturate != inst->Instruction.Saturate ) {
      TXT( "\nSaturate   : " );
      ENM( inst->Instruction.Saturate, TGSI_SATS );
   }
   if( deflt || fi->Instruction.NumDstRegs != inst->Instruction.NumDstRegs ) {
      TXT( "\nNumDstRegs : " );
      UID( inst->Instruction.NumDstRegs );
   }
   if( deflt || fi->Instruction.NumSrcRegs != inst->Instruction.NumSrcRegs ) {
      TXT( "\nNumSrcRegs : " );
      UID( inst->Instruction.NumSrcRegs );
   }
   if( ignored ) {
      TXT( "\nPadding    : " );
      UIX( inst->Instruction.Padding );
   }

   if( deflt || tgsi_compare_instruction_ext_nv( inst->InstructionExtNv, fi->InstructionExtNv ) ) {
      EOL();
      TXT( "\nType          : " );
      ENM( inst->InstructionExtNv.Type, TGSI_INSTRUCTION_EXTS );
      if( deflt || fi->InstructionExtNv.Precision != inst->InstructionExtNv.Precision ) {
         TXT( "\nPrecision     : " );
         ENM( inst->InstructionExtNv.Precision, TGSI_PRECISIONS );
      }
      if( deflt || fi->InstructionExtNv.CondDstIndex != inst->InstructionExtNv.CondDstIndex ) {
         TXT( "\nCondDstIndex  : " );
         UID( inst->InstructionExtNv.CondDstIndex );
      }
      if( deflt || fi->InstructionExtNv.CondFlowIndex != inst->InstructionExtNv.CondFlowIndex ) {
         TXT( "\nCondFlowIndex : " );
         UID( inst->InstructionExtNv.CondFlowIndex );
      }
      if( deflt || fi->InstructionExtNv.CondMask != inst->InstructionExtNv.CondMask ) {
         TXT( "\nCondMask      : " );
         ENM( inst->InstructionExtNv.CondMask, TGSI_CCS );
      }
      if( deflt || fi->InstructionExtNv.CondSwizzleX != inst->InstructionExtNv.CondSwizzleX ) {
         TXT( "\nCondSwizzleX  : " );
         ENM( inst->InstructionExtNv.CondSwizzleX, TGSI_SWIZZLES );
      }
      if( deflt || fi->InstructionExtNv.CondSwizzleY != inst->InstructionExtNv.CondSwizzleY ) {
         TXT( "\nCondSwizzleY  : " );
         ENM( inst->InstructionExtNv.CondSwizzleY, TGSI_SWIZZLES );
      }
      if( deflt || fi->InstructionExtNv.CondSwizzleZ != inst->InstructionExtNv.CondSwizzleZ ) {
         TXT( "\nCondSwizzleZ  : " );
         ENM( inst->InstructionExtNv.CondSwizzleZ, TGSI_SWIZZLES );
      }
      if( deflt || fi->InstructionExtNv.CondSwizzleW != inst->InstructionExtNv.CondSwizzleW ) {
         TXT( "\nCondSwizzleW  : " );
         ENM( inst->InstructionExtNv.CondSwizzleW, TGSI_SWIZZLES );
      }
      if( deflt || fi->InstructionExtNv.CondDstUpdate != inst->InstructionExtNv.CondDstUpdate ) {
         TXT( "\nCondDstUpdate : " );
         UID( inst->InstructionExtNv.CondDstUpdate );
      }
      if( deflt || fi->InstructionExtNv.CondFlowEnable != inst->InstructionExtNv.CondFlowEnable ) {
         TXT( "\nCondFlowEnable: " );
         UID( inst->InstructionExtNv.CondFlowEnable );
      }
      if( ignored ) {
         TXT( "\nPadding       : " );
         UIX( inst->InstructionExtNv.Padding );
         if( deflt || fi->InstructionExtNv.Extended != inst->InstructionExtNv.Extended ) {
            TXT( "\nExtended      : " );
            UID( inst->InstructionExtNv.Extended );
         }
      }
   }

   if( deflt || tgsi_compare_instruction_ext_label( inst->InstructionExtLabel, fi->InstructionExtLabel ) ) {
      EOL();
      TXT( "\nType    : " );
      ENM( inst->InstructionExtLabel.Type, TGSI_INSTRUCTION_EXTS );
      if( deflt || fi->InstructionExtLabel.Label != inst->InstructionExtLabel.Label ) {
         TXT( "\nLabel   : " );
         UID( inst->InstructionExtLabel.Label );
      }
      if( ignored ) {
         TXT( "\nPadding : " );
         UIX( inst->InstructionExtLabel.Padding );
         if( deflt || fi->InstructionExtLabel.Extended != inst->InstructionExtLabel.Extended ) {
            TXT( "\nExtended: " );
            UID( inst->InstructionExtLabel.Extended );
         }
      }
   }

   if( deflt || tgsi_compare_instruction_ext_texture( inst->InstructionExtTexture, fi->InstructionExtTexture ) ) {
      EOL();
      TXT( "\nType    : " );
      ENM( inst->InstructionExtTexture.Type, TGSI_INSTRUCTION_EXTS );
      if( deflt || fi->InstructionExtTexture.Texture != inst->InstructionExtTexture.Texture ) {
         TXT( "\nTexture : " );
         ENM( inst->InstructionExtTexture.Texture, TGSI_TEXTURES );
      }
      if( ignored ) {
         TXT( "\nPadding : " );
         UIX( inst->InstructionExtTexture.Padding );
         if( deflt || fi->InstructionExtTexture.Extended != inst->InstructionExtTexture.Extended ) {
            TXT( "\nExtended: " );
            UID( inst->InstructionExtTexture.Extended );
         }
      }
   }

   for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
      struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
      struct tgsi_full_dst_register *fd = &fi->FullDstRegisters[i];

      EOL();
      TXT( "\nFile     : " );
      ENM( dst->DstRegister.File, TGSI_FILES );
      if( deflt || fd->DstRegister.WriteMask != dst->DstRegister.WriteMask ) {
         TXT( "\nWriteMask: " );
         ENM( dst->DstRegister.WriteMask, TGSI_WRITEMASKS );
      }
      if( ignored ) {
         if( deflt || fd->DstRegister.Indirect != dst->DstRegister.Indirect ) {
            TXT( "\nIndirect : " );
            UID( dst->DstRegister.Indirect );
         }
         if( deflt || fd->DstRegister.Dimension != dst->DstRegister.Dimension ) {
            TXT( "\nDimension: " );
            UID( dst->DstRegister.Dimension );
         }
      }
      if( deflt || fd->DstRegister.Index != dst->DstRegister.Index ) {
         TXT( "\nIndex    : " );
         SID( dst->DstRegister.Index );
      }
      if( ignored ) {
         TXT( "\nPadding  : " );
         UIX( dst->DstRegister.Padding );
         if( deflt || fd->DstRegister.Extended != dst->DstRegister.Extended ) {
            TXT( "\nExtended : " );
            UID( dst->DstRegister.Extended );
         }
      }

      if( deflt || tgsi_compare_dst_register_ext_concode( dst->DstRegisterExtConcode, fd->DstRegisterExtConcode ) ) {
         EOL();
         TXT( "\nType        : " );
         ENM( dst->DstRegisterExtConcode.Type, TGSI_DST_REGISTER_EXTS );
         if( deflt || fd->DstRegisterExtConcode.CondMask != dst->DstRegisterExtConcode.CondMask ) {
            TXT( "\nCondMask    : " );
            ENM( dst->DstRegisterExtConcode.CondMask, TGSI_CCS );
         }
         if( deflt || fd->DstRegisterExtConcode.CondSwizzleX != dst->DstRegisterExtConcode.CondSwizzleX ) {
            TXT( "\nCondSwizzleX: " );
            ENM( dst->DstRegisterExtConcode.CondSwizzleX, TGSI_SWIZZLES );
         }
         if( deflt || fd->DstRegisterExtConcode.CondSwizzleY != dst->DstRegisterExtConcode.CondSwizzleY ) {
            TXT( "\nCondSwizzleY: " );
            ENM( dst->DstRegisterExtConcode.CondSwizzleY, TGSI_SWIZZLES );
         }
         if( deflt || fd->DstRegisterExtConcode.CondSwizzleZ != dst->DstRegisterExtConcode.CondSwizzleZ ) {
            TXT( "\nCondSwizzleZ: " );
            ENM( dst->DstRegisterExtConcode.CondSwizzleZ, TGSI_SWIZZLES );
         }
         if( deflt || fd->DstRegisterExtConcode.CondSwizzleW != dst->DstRegisterExtConcode.CondSwizzleW ) {
            TXT( "\nCondSwizzleW: " );
            ENM( dst->DstRegisterExtConcode.CondSwizzleW, TGSI_SWIZZLES );
         }
         if( deflt || fd->DstRegisterExtConcode.CondSrcIndex != dst->DstRegisterExtConcode.CondSrcIndex ) {
            TXT( "\nCondSrcIndex: " );
            UID( dst->DstRegisterExtConcode.CondSrcIndex );
         }
         if( ignored ) {
            TXT( "\nPadding     : " );
            UIX( dst->DstRegisterExtConcode.Padding );
            if( deflt || fd->DstRegisterExtConcode.Extended != dst->DstRegisterExtConcode.Extended ) {
               TXT( "\nExtended    : " );
               UID( dst->DstRegisterExtConcode.Extended );
            }
         }
      }

      if( deflt || tgsi_compare_dst_register_ext_modulate( dst->DstRegisterExtModulate, fd->DstRegisterExtModulate ) ) {
         EOL();
         TXT( "\nType    : " );
         ENM( dst->DstRegisterExtModulate.Type, TGSI_DST_REGISTER_EXTS );
         if( deflt || fd->DstRegisterExtModulate.Modulate != dst->DstRegisterExtModulate.Modulate ) {
            TXT( "\nModulate: " );
            ENM( dst->DstRegisterExtModulate.Modulate, TGSI_MODULATES );
         }
         if( ignored ) {
            TXT( "\nPadding : " );
            UIX( dst->DstRegisterExtModulate.Padding );
            if( deflt || fd->DstRegisterExtModulate.Extended != dst->DstRegisterExtModulate.Extended ) {
               TXT( "\nExtended: " );
               UID( dst->DstRegisterExtModulate.Extended );
            }
         }
      }
   }

   for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
      struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
      struct tgsi_full_src_register *fs = &fi->FullSrcRegisters[i];

      EOL();
      TXT( "\nFile     : ");
      ENM( src->SrcRegister.File, TGSI_FILES );
      if( deflt || fs->SrcRegister.SwizzleX != src->SrcRegister.SwizzleX ) {
         TXT( "\nSwizzleX : " );
         ENM( src->SrcRegister.SwizzleX, TGSI_SWIZZLES );
      }
      if( deflt || fs->SrcRegister.SwizzleY != src->SrcRegister.SwizzleY ) {
         TXT( "\nSwizzleY : " );
         ENM( src->SrcRegister.SwizzleY, TGSI_SWIZZLES );
      }
      if( deflt || fs->SrcRegister.SwizzleZ != src->SrcRegister.SwizzleZ ) {
         TXT( "\nSwizzleZ : " );
         ENM( src->SrcRegister.SwizzleZ, TGSI_SWIZZLES );
      }
      if( deflt || fs->SrcRegister.SwizzleW != src->SrcRegister.SwizzleW ) {
         TXT( "\nSwizzleW : " );
         ENM( src->SrcRegister.SwizzleW, TGSI_SWIZZLES );
      }
      if( deflt || fs->SrcRegister.Negate != src->SrcRegister.Negate ) {
         TXT( "\nNegate   : " );
         UID( src->SrcRegister.Negate );
      }
      if( ignored ) {
         if( deflt || fs->SrcRegister.Indirect != src->SrcRegister.Indirect ) {
            TXT( "\nIndirect : " );
            UID( src->SrcRegister.Indirect );
         }
         if( deflt || fs->SrcRegister.Dimension != src->SrcRegister.Dimension ) {
            TXT( "\nDimension: " );
            UID( src->SrcRegister.Dimension );
         }
      }
      if( deflt || fs->SrcRegister.Index != src->SrcRegister.Index ) {
         TXT( "\nIndex    : " );
         SID( src->SrcRegister.Index );
      }
      if( ignored ) {
         if( deflt || fs->SrcRegister.Extended != src->SrcRegister.Extended ) {
            TXT( "\nExtended : " );
            UID( src->SrcRegister.Extended );
         }
      }

      if( deflt || tgsi_compare_src_register_ext_swz( src->SrcRegisterExtSwz, fs->SrcRegisterExtSwz ) ) {
         EOL();
         TXT( "\nType       : " );
         ENM( src->SrcRegisterExtSwz.Type, TGSI_SRC_REGISTER_EXTS );
         if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleX != src->SrcRegisterExtSwz.ExtSwizzleX ) {
            TXT( "\nExtSwizzleX: " );
            ENM( src->SrcRegisterExtSwz.ExtSwizzleX, TGSI_EXTSWIZZLES );
         }
         if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleY != src->SrcRegisterExtSwz.ExtSwizzleY ) {
            TXT( "\nExtSwizzleY: " );
            ENM( src->SrcRegisterExtSwz.ExtSwizzleY, TGSI_EXTSWIZZLES );
         }
         if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleZ != src->SrcRegisterExtSwz.ExtSwizzleZ ) {
            TXT( "\nExtSwizzleZ: " );
            ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, TGSI_EXTSWIZZLES );
         }
         if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleW != src->SrcRegisterExtSwz.ExtSwizzleW ) {
            TXT( "\nExtSwizzleW: " );
            ENM( src->SrcRegisterExtSwz.ExtSwizzleW, TGSI_EXTSWIZZLES );
         }
         if( deflt || fs->SrcRegisterExtSwz.NegateX != src->SrcRegisterExtSwz.NegateX ) {
            TXT( "\nNegateX   : " );
            UID( src->SrcRegisterExtSwz.NegateX );
         }
         if( deflt || fs->SrcRegisterExtSwz.NegateY != src->SrcRegisterExtSwz.NegateY ) {
            TXT( "\nNegateY   : " );
            UID( src->SrcRegisterExtSwz.NegateY );
         }
         if( deflt || fs->SrcRegisterExtSwz.NegateZ != src->SrcRegisterExtSwz.NegateZ ) {
            TXT( "\nNegateZ   : " );
            UID( src->SrcRegisterExtSwz.NegateZ );
         }
         if( deflt || fs->SrcRegisterExtSwz.NegateW != src->SrcRegisterExtSwz.NegateW ) {
            TXT( "\nNegateW   : " );
            UID( src->SrcRegisterExtSwz.NegateW );
         }
         if( ignored ) {
            TXT( "\nPadding   : " );
            UIX( src->SrcRegisterExtSwz.Padding );
            if( deflt || fs->SrcRegisterExtSwz.Extended != src->SrcRegisterExtSwz.Extended ) {
               TXT( "\nExtended   : " );
               UID( src->SrcRegisterExtSwz.Extended );
            }
         }
      }

      if( deflt || tgsi_compare_src_register_ext_mod( src->SrcRegisterExtMod, fs->SrcRegisterExtMod ) ) {
         EOL();
         TXT( "\nType     : " );
         ENM( src->SrcRegisterExtMod.Type, TGSI_SRC_REGISTER_EXTS );
         if( deflt || fs->SrcRegisterExtMod.Complement != src->SrcRegisterExtMod.Complement ) {
            TXT( "\nComplement: " );
            UID( src->SrcRegisterExtMod.Complement );
         }
         if( deflt || fs->SrcRegisterExtMod.Bias != src->SrcRegisterExtMod.Bias ) {
            TXT( "\nBias     : " );
            UID( src->SrcRegisterExtMod.Bias );
         }
         if( deflt || fs->SrcRegisterExtMod.Scale2X != src->SrcRegisterExtMod.Scale2X ) {
            TXT( "\nScale2X   : " );
            UID( src->SrcRegisterExtMod.Scale2X );
         }
         if( deflt || fs->SrcRegisterExtMod.Absolute != src->SrcRegisterExtMod.Absolute ) {
            TXT( "\nAbsolute  : " );
            UID( src->SrcRegisterExtMod.Absolute );
         }
         if( deflt || fs->SrcRegisterExtMod.Negate != src->SrcRegisterExtMod.Negate ) {
            TXT( "\nNegate   : " );
            UID( src->SrcRegisterExtMod.Negate );
         }
         if( ignored ) {
            TXT( "\nPadding   : " );
            UIX( src->SrcRegisterExtMod.Padding );
            if( deflt || fs->SrcRegisterExtMod.Extended != src->SrcRegisterExtMod.Extended ) {
               TXT( "\nExtended  : " );
               UID( src->SrcRegisterExtMod.Extended );
            }
         }
      }
   }
}
Example #10
0
static void
scan_instruction(struct tgsi_shader_info *info,
                 const struct tgsi_full_instruction *fullinst,
                 unsigned *current_depth)
{
   unsigned i;
   bool is_mem_inst = false;

   assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
   info->opcode_count[fullinst->Instruction.Opcode]++;

   switch (fullinst->Instruction.Opcode) {
   case TGSI_OPCODE_IF:
   case TGSI_OPCODE_UIF:
   case TGSI_OPCODE_BGNLOOP:
      (*current_depth)++;
      info->max_depth = MAX2(info->max_depth, *current_depth);
      break;
   case TGSI_OPCODE_ENDIF:
   case TGSI_OPCODE_ENDLOOP:
      (*current_depth)--;
      break;
   default:
      break;
   }

   if (fullinst->Instruction.Opcode == TGSI_OPCODE_INTERP_CENTROID ||
       fullinst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET ||
       fullinst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE) {
      const struct tgsi_full_src_register *src0 = &fullinst->Src[0];
      unsigned input;

      if (src0->Register.Indirect && src0->Indirect.ArrayID)
         input = info->input_array_first[src0->Indirect.ArrayID];
      else
         input = src0->Register.Index;

      /* For the INTERP opcodes, the interpolation is always
       * PERSPECTIVE unless LINEAR is specified.
       */
      switch (info->input_interpolate[input]) {
      case TGSI_INTERPOLATE_COLOR:
      case TGSI_INTERPOLATE_CONSTANT:
      case TGSI_INTERPOLATE_PERSPECTIVE:
         switch (fullinst->Instruction.Opcode) {
         case TGSI_OPCODE_INTERP_CENTROID:
            info->uses_persp_opcode_interp_centroid = TRUE;
            break;
         case TGSI_OPCODE_INTERP_OFFSET:
            info->uses_persp_opcode_interp_offset = TRUE;
            break;
         case TGSI_OPCODE_INTERP_SAMPLE:
            info->uses_persp_opcode_interp_sample = TRUE;
            break;
         }
         break;

      case TGSI_INTERPOLATE_LINEAR:
         switch (fullinst->Instruction.Opcode) {
         case TGSI_OPCODE_INTERP_CENTROID:
            info->uses_linear_opcode_interp_centroid = TRUE;
            break;
         case TGSI_OPCODE_INTERP_OFFSET:
            info->uses_linear_opcode_interp_offset = TRUE;
            break;
         case TGSI_OPCODE_INTERP_SAMPLE:
            info->uses_linear_opcode_interp_sample = TRUE;
            break;
         }
         break;
      }
   }

   if (fullinst->Instruction.Opcode >= TGSI_OPCODE_F2D &&
       fullinst->Instruction.Opcode <= TGSI_OPCODE_DSSG)
      info->uses_doubles = TRUE;

   for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
      const struct tgsi_full_src_register *src = &fullinst->Src[i];
      int ind = src->Register.Index;

      /* Mark which inputs are effectively used */
      if (src->Register.File == TGSI_FILE_INPUT) {
         unsigned usage_mask;
         usage_mask = tgsi_util_get_inst_usage_mask(fullinst, i);
         if (src->Register.Indirect) {
            for (ind = 0; ind < info->num_inputs; ++ind) {
               info->input_usage_mask[ind] |= usage_mask;
            }
         } else {
            assert(ind >= 0);
            assert(ind < PIPE_MAX_SHADER_INPUTS);
            info->input_usage_mask[ind] |= usage_mask;
         }

         if (info->processor == PIPE_SHADER_FRAGMENT &&
             !src->Register.Indirect) {
            unsigned name =
               info->input_semantic_name[src->Register.Index];
            unsigned index =
               info->input_semantic_index[src->Register.Index];

            if (name == TGSI_SEMANTIC_POSITION &&
                (src->Register.SwizzleX == TGSI_SWIZZLE_Z ||
                 src->Register.SwizzleY == TGSI_SWIZZLE_Z ||
                 src->Register.SwizzleZ == TGSI_SWIZZLE_Z ||
                 src->Register.SwizzleW == TGSI_SWIZZLE_Z))
               info->reads_z = TRUE;

            if (name == TGSI_SEMANTIC_COLOR) {
               unsigned mask =
                  (1 << src->Register.SwizzleX) |
                  (1 << src->Register.SwizzleY) |
                  (1 << src->Register.SwizzleZ) |
                  (1 << src->Register.SwizzleW);

               info->colors_read |= mask << (index * 4);
            }
         }
      }

      /* check for indirect register reads */
      if (src->Register.Indirect) {
         info->indirect_files |= (1 << src->Register.File);
         info->indirect_files_read |= (1 << src->Register.File);
      }

      /* Texture samplers */
      if (src->Register.File == TGSI_FILE_SAMPLER) {
         const unsigned index = src->Register.Index;

         assert(fullinst->Instruction.Texture);
         assert(index < ARRAY_SIZE(info->is_msaa_sampler));
         assert(index < PIPE_MAX_SAMPLERS);

         if (is_texture_inst(fullinst->Instruction.Opcode)) {
            const unsigned target = fullinst->Texture.Texture;
            assert(target < TGSI_TEXTURE_UNKNOWN);
            /* for texture instructions, check that the texture instruction
             * target matches the previous sampler view declaration (if there
             * was one.)
             */
            if (info->sampler_targets[index] == TGSI_TEXTURE_UNKNOWN) {
               /* probably no sampler view declaration */
               info->sampler_targets[index] = target;
            } else {
               /* Make sure the texture instruction's sampler/target info
                * agrees with the sampler view declaration.
                */
               assert(info->sampler_targets[index] == target);
            }
            /* MSAA samplers */
            if (target == TGSI_TEXTURE_2D_MSAA ||
                target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
               info->is_msaa_sampler[src->Register.Index] = TRUE;
            }
         }
      }

      if (is_memory_file(src->Register.File)) {
         is_mem_inst = true;

         if (tgsi_get_opcode_info(fullinst->Instruction.Opcode)->is_store) {
            info->writes_memory = TRUE;

            if (src->Register.File == TGSI_FILE_IMAGE &&
                !src->Register.Indirect)
               info->images_writemask |= 1 << src->Register.Index;
         }
      }
   }

   /* check for indirect register writes */
   for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) {
      const struct tgsi_full_dst_register *dst = &fullinst->Dst[i];
      if (dst->Register.Indirect) {
         info->indirect_files |= (1 << dst->Register.File);
         info->indirect_files_written |= (1 << dst->Register.File);
      }

      if (is_memory_file(dst->Register.File)) {
         assert(fullinst->Instruction.Opcode == TGSI_OPCODE_STORE);

         is_mem_inst = true;
         info->writes_memory = TRUE;

         if (dst->Register.File == TGSI_FILE_IMAGE &&
             !dst->Register.Indirect)
            info->images_writemask |= 1 << dst->Register.Index;
      }
   }

   if (is_mem_inst)
      info->num_memory_instructions++;

   info->num_instructions++;
}
Example #11
0
static boolean
iter_instruction(
   struct tgsi_iterate_context *iter,
   struct tgsi_full_instruction *inst )
{
   struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
   const struct tgsi_opcode_info *info;
   uint i;

   if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
      if (ctx->index_of_END != ~0) {
         report_error( ctx, "Too many END instructions" );
      }
      ctx->index_of_END = ctx->num_instructions;
   }

   info = tgsi_get_opcode_info( inst->Instruction.Opcode );
   if (info == NULL) {
      report_error( ctx, "(%u): Invalid instruction opcode", inst->Instruction.Opcode );
      return TRUE;
   }

   if (info->num_dst != inst->Instruction.NumDstRegs) {
      report_error( ctx, "Invalid number of destination operands, should be %u", info->num_dst );
   }
   if (info->num_src != inst->Instruction.NumSrcRegs) {
      report_error( ctx, "Invalid number of source operands, should be %u", info->num_src );
   }

   /* Check destination and source registers' validity.
    * Mark the registers as used.
    */
   for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
      check_register_usage(
         ctx,
         inst->FullDstRegisters[i].DstRegister.File,
         inst->FullDstRegisters[i].DstRegister.Index,
         "destination",
         FALSE );
   }
   for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
      check_register_usage(
         ctx,
         inst->FullSrcRegisters[i].SrcRegister.File,
         inst->FullSrcRegisters[i].SrcRegister.Index,
         "source",
         (boolean)inst->FullSrcRegisters[i].SrcRegister.Indirect );
      if (inst->FullSrcRegisters[i].SrcRegister.Indirect) {
         uint file;
         int index;

         file = inst->FullSrcRegisters[i].SrcRegisterInd.File;
         index = inst->FullSrcRegisters[i].SrcRegisterInd.Index;
         check_register_usage(
            ctx,
            file,
            index,
            "indirect",
            FALSE );
         if (file != TGSI_FILE_ADDRESS || index != 0)
            report_warning( ctx, "Indirect register not ADDR[0]" );
      }
   }

   ctx->num_instructions++;

   return TRUE;
}
Example #12
0
static boolean
iter_instruction(
   struct tgsi_iterate_context *iter,
   struct tgsi_full_instruction *inst )
{
   struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
   const struct tgsi_opcode_info *info;
   uint i;

   if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
      if (ctx->index_of_END != ~0) {
         report_error( ctx, "Too many END instructions" );
      }
      ctx->index_of_END = ctx->num_instructions;
   }

   info = tgsi_get_opcode_info( inst->Instruction.Opcode );
   if (!info) {
      report_error( ctx, "(%u): Invalid instruction opcode", inst->Instruction.Opcode );
      return TRUE;
   }

   if (info->num_dst != inst->Instruction.NumDstRegs) {
      report_error( ctx, "%s: Invalid number of destination operands, should be %u", info->mnemonic, info->num_dst );
   }
   if (info->num_src != inst->Instruction.NumSrcRegs) {
      report_error( ctx, "%s: Invalid number of source operands, should be %u", info->mnemonic, info->num_src );
   }

   /* Check destination and source registers' validity.
    * Mark the registers as used.
    */
   for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
      scan_register *reg = create_scan_register_dst(&inst->Dst[i]);
      check_register_usage(
         ctx,
         reg,
         "destination",
         FALSE );
      if (!inst->Dst[i].Register.WriteMask) {
         report_error(ctx, "Destination register has empty writemask");
      }
   }
   for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
      scan_register *reg = create_scan_register_src(&inst->Src[i]);
      check_register_usage(
         ctx,
         reg,
         "source",
         (boolean)inst->Src[i].Register.Indirect );
      if (inst->Src[i].Register.Indirect) {
         scan_register *ind_reg = MALLOC(sizeof(scan_register));

         fill_scan_register1d(ind_reg,
                              inst->Src[i].Indirect.File,
                              inst->Src[i].Indirect.Index);
         check_register_usage(
            ctx,
            ind_reg,
            "indirect",
            FALSE );
      }
   }

   ctx->num_instructions++;

   return TRUE;
}
Example #13
0
static boolean
parse_instruction(
   struct translate_ctx *ctx,
   boolean has_label )
{
   uint i;
   uint saturate = TGSI_SAT_NONE;
   const struct tgsi_opcode_info *info;
   struct tgsi_full_instruction inst;
   uint advance;

   inst = tgsi_default_full_instruction();

   /* Parse predicate.
    */
   eat_opt_white( &ctx->cur );
   if (*ctx->cur == '(') {
      uint file;
      int index;
      uint swizzle[4];
      boolean parsed_swizzle;

      inst.Instruction.Predicate = 1;

      ctx->cur++;
      if (*ctx->cur == '!') {
         ctx->cur++;
         inst.Predicate.Negate = 1;
      }

      if (!parse_register_1d( ctx, &file, &index ))
         return FALSE;

      if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
         if (parsed_swizzle) {
            inst.Predicate.SwizzleX = swizzle[0];
            inst.Predicate.SwizzleY = swizzle[1];
            inst.Predicate.SwizzleZ = swizzle[2];
            inst.Predicate.SwizzleW = swizzle[3];
         }
      }

      if (*ctx->cur != ')') {
         report_error( ctx, "Expected `)'" );
         return FALSE;
      }

      ctx->cur++;
   }

   /* Parse instruction name.
    */
   eat_opt_white( &ctx->cur );
   for (i = 0; i < TGSI_OPCODE_LAST; i++) {
      const char *cur = ctx->cur;

      info = tgsi_get_opcode_info( i );
      if (match_inst_mnemonic(&cur, info)) {
         if (str_match_no_case( &cur, "_SATNV" ))
            saturate = TGSI_SAT_MINUS_PLUS_ONE;
         else if (str_match_no_case( &cur, "_SAT" ))
            saturate = TGSI_SAT_ZERO_ONE;

         if (info->num_dst + info->num_src + info->is_tex == 0) {
            if (!is_digit_alpha_underscore( cur )) {
               ctx->cur = cur;
               break;
            }
         }
         else if (*cur == '\0' || eat_white( &cur )) {
            ctx->cur = cur;
            break;
         }
      }
   }
   if (i == TGSI_OPCODE_LAST) {
      if (has_label)
         report_error( ctx, "Unknown opcode" );
      else
         report_error( ctx, "Expected `DCL', `IMM' or a label" );
      return FALSE;
   }

   inst.Instruction.Opcode = i;
   inst.Instruction.Saturate = saturate;
   inst.Instruction.NumDstRegs = info->num_dst;
   inst.Instruction.NumSrcRegs = info->num_src;

   /* Parse instruction operands.
    */
   for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
      if (i > 0) {
         eat_opt_white( &ctx->cur );
         if (*ctx->cur != ',') {
            report_error( ctx, "Expected `,'" );
            return FALSE;
         }
         ctx->cur++;
         eat_opt_white( &ctx->cur );
      }

      if (i < info->num_dst) {
         if (!parse_dst_operand( ctx, &inst.Dst[i] ))
            return FALSE;
      }
      else if (i < info->num_dst + info->num_src) {
         if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
            return FALSE;
      }
      else {
         uint j;

         for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
            if (str_match_no_case( &ctx->cur, texture_names[j] )) {
               if (!is_digit_alpha_underscore( ctx->cur )) {
                  inst.Instruction.Texture = 1;
                  inst.Texture.Texture = j;
                  break;
               }
            }
         }
         if (j == TGSI_TEXTURE_COUNT) {
            report_error( ctx, "Expected texture target" );
            return FALSE;
         }
      }
   }

   if (info->is_branch) {
      uint target;

      eat_opt_white( &ctx->cur );
      if (*ctx->cur != ':') {
         report_error( ctx, "Expected `:'" );
         return FALSE;
      }
      ctx->cur++;
      eat_opt_white( &ctx->cur );
      if (!parse_uint( &ctx->cur, &target )) {
         report_error( ctx, "Expected a label" );
         return FALSE;
      }
      inst.Instruction.Label = 1;
      inst.Label.Label = target;
   }

   advance = tgsi_build_full_instruction(
      &inst,
      ctx->tokens_cur,
      ctx->header,
      (uint) (ctx->tokens_end - ctx->tokens_cur) );
   if (advance == 0)
      return FALSE;
   ctx->tokens_cur += advance;

   return TRUE;
}
Example #14
0
static boolean
parse_instruction(
   struct translate_ctx *ctx,
   boolean has_label )
{
   uint i;
   uint saturate = 0;
   uint precise = 0;
   const struct tgsi_opcode_info *info;
   struct tgsi_full_instruction inst;
   const char *cur;
   uint advance;

   inst = tgsi_default_full_instruction();

   /* Parse instruction name.
    */
   eat_opt_white( &ctx->cur );
   for (i = 0; i < TGSI_OPCODE_LAST; i++) {
      cur = ctx->cur;

      info = tgsi_get_opcode_info( i );
      if (match_inst(&cur, &saturate, &precise, info)) {
         if (info->num_dst + info->num_src + info->is_tex == 0) {
            ctx->cur = cur;
            break;
         }
         else if (*cur == '\0' || eat_white( &cur )) {
            ctx->cur = cur;
            break;
         }
      }
   }
   if (i == TGSI_OPCODE_LAST) {
      if (has_label)
         report_error( ctx, "Unknown opcode" );
      else
         report_error( ctx, "Expected `DCL', `IMM' or a label" );
      return FALSE;
   }

   inst.Instruction.Opcode = i;
   inst.Instruction.Saturate = saturate;
   inst.Instruction.Precise = precise;
   inst.Instruction.NumDstRegs = info->num_dst;
   inst.Instruction.NumSrcRegs = info->num_src;

   if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
      /*
       * These are not considered tex opcodes here (no additional
       * target argument) however we're required to set the Texture
       * bit so we can set the number of tex offsets.
       */
      inst.Instruction.Texture = 1;
      inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
   }

   if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) ||
       i == TGSI_OPCODE_RESQ) {
      inst.Instruction.Memory = 1;
      inst.Memory.Qualifier = 0;
   }

   assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS);
   assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS);

   /* Parse instruction operands.
    */
   for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
      if (i > 0) {
         eat_opt_white( &ctx->cur );
         if (*ctx->cur != ',') {
            report_error( ctx, "Expected `,'" );
            return FALSE;
         }
         ctx->cur++;
         eat_opt_white( &ctx->cur );
      }

      if (i < info->num_dst) {
         if (!parse_dst_operand( ctx, &inst.Dst[i] ))
            return FALSE;
      }
      else if (i < info->num_dst + info->num_src) {
         if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
            return FALSE;
      }
      else {
         uint j;

         for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
            if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
               inst.Instruction.Texture = 1;
               inst.Texture.Texture = j;
               break;
            }
         }
         if (j == TGSI_TEXTURE_COUNT) {
            report_error( ctx, "Expected texture target" );
            return FALSE;
         }
      }
   }

   cur = ctx->cur;
   eat_opt_white( &cur );
   for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) {
         cur++;
         eat_opt_white( &cur );
         ctx->cur = cur;
         if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] ))
            return FALSE;
         cur = ctx->cur;
         eat_opt_white( &cur );
   }
   inst.Texture.NumOffsets = i;

   cur = ctx->cur;
   eat_opt_white(&cur);

   for (; inst.Instruction.Memory && *cur == ',';
        ctx->cur = cur, eat_opt_white(&cur)) {
      int j;

      cur++;
      eat_opt_white(&cur);

      j = str_match_name_from_array(&cur, tgsi_memory_names,
                                    ARRAY_SIZE(tgsi_memory_names));
      if (j >= 0) {
         inst.Memory.Qualifier |= 1U << j;
         continue;
      }

      j = str_match_name_from_array(&cur, tgsi_texture_names,
                                    ARRAY_SIZE(tgsi_texture_names));
      if (j >= 0) {
         inst.Memory.Texture = j;
         continue;
      }

      j = str_match_format(&cur);
      if (j >= 0) {
         inst.Memory.Format = j;
         continue;
      }

      ctx->cur = cur;
      report_error(ctx, "Expected memory qualifier, texture target, or format\n");
      return FALSE;
   }

   cur = ctx->cur;
   eat_opt_white( &cur );
   if (info->is_branch && *cur == ':') {
      uint target;

      cur++;
      eat_opt_white( &cur );
      if (!parse_uint( &cur, &target )) {
         report_error( ctx, "Expected a label" );
         return FALSE;
      }
      inst.Instruction.Label = 1;
      inst.Label.Label = target;
      ctx->cur = cur;
   }

   advance = tgsi_build_full_instruction(
      &inst,
      ctx->tokens_cur,
      ctx->header,
      (uint) (ctx->tokens_end - ctx->tokens_cur) );
   if (advance == 0)
      return FALSE;
   ctx->tokens_cur += advance;

   return TRUE;
}