예제 #1
0
static boolean
parse_register_bracket(
   struct translate_ctx *ctx,
   struct parsed_bracket *brackets)
{
   const char *cur;
   uint uindex;

   memset(brackets, 0, sizeof(struct parsed_bracket));

   eat_opt_white( &ctx->cur );

   cur = ctx->cur;
   if (parse_file( &cur, &brackets->ind_file )) {
      if (!parse_register_1d( ctx, &brackets->ind_file,
                              &brackets->ind_index ))
         return FALSE;
      eat_opt_white( &ctx->cur );

      if (*ctx->cur == '.') {
         ctx->cur++;
         eat_opt_white(&ctx->cur);

         switch (uprcase(*ctx->cur)) {
         case 'X':
            brackets->ind_comp = TGSI_SWIZZLE_X;
            break;
         case 'Y':
            brackets->ind_comp = TGSI_SWIZZLE_Y;
            break;
         case 'Z':
            brackets->ind_comp = TGSI_SWIZZLE_Z;
            break;
         case 'W':
            brackets->ind_comp = TGSI_SWIZZLE_W;
            break;
         default:
            report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
            return FALSE;
         }
         ctx->cur++;
         eat_opt_white(&ctx->cur);
      }

      if (*ctx->cur == '+' || *ctx->cur == '-')
         parse_int( &ctx->cur, &brackets->index );
      else
         brackets->index = 0;
   }
   else {
      if (!parse_uint( &ctx->cur, &uindex )) {
         report_error( ctx, "Expected literal unsigned integer" );
         return FALSE;
      }
      brackets->index = (int) uindex;
      brackets->ind_file = TGSI_FILE_NULL;
      brackets->ind_index = 0;
   }
   eat_opt_white( &ctx->cur );
   if (*ctx->cur != ']') {
      report_error( ctx, "Expected `]'" );
      return FALSE;
   }
   ctx->cur++;
   if (*ctx->cur == '(') {
      ctx->cur++;
      eat_opt_white( &ctx->cur );
      if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
         report_error( ctx, "Expected literal unsigned integer" );
         return FALSE;
      }
      eat_opt_white( &ctx->cur );
      if (*ctx->cur != ')') {
         report_error( ctx, "Expected `)'" );
         return FALSE;
      }
      ctx->cur++;
   }
   return TRUE;
}
예제 #2
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;
}
예제 #3
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;
}