return *str1 == 0 && *str2 == 0;
}
+/* Return TRUE if both strings match.
+ * The second string is terminated by zero.
+ * The pointer to the first string is moved at end of the read word
+ * on success.
+ */
static boolean str_match_no_case( const char **pcur, const char *str )
{
const char *cur = *pcur;
return FALSE;
}
+/* Return TRUE if both strings match.
+ * The first string is be terminated by a non-digit non-letter non-underscore
+ * character, the second string is terminated by zero.
+ * The pointer to the first string is moved at end of the read word
+ * on success.
+ */
+static boolean str_match_nocase_whole( const char **pcur, const char *str )
+{
+ const char *cur = *pcur;
+
+ if (str_match_no_case(&cur, str) &&
+ !is_digit_alpha_underscore(cur)) {
+ *pcur = cur;
+ return TRUE;
+ }
+ return FALSE;
+}
+
/* Eat zero or more whitespaces.
*/
static void eat_opt_white( const char **pcur )
struct tgsi_header *header;
unsigned processor : 4;
int implied_array_size : 5;
+ unsigned num_immediates;
};
static void report_error( struct translate_ctx *ctx, const char *msg )
{
uint processor;
- if (str_match_no_case( &ctx->cur, "FRAG" ))
+ if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
processor = TGSI_PROCESSOR_FRAGMENT;
- else if (str_match_no_case( &ctx->cur, "VERT" ))
+ else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
processor = TGSI_PROCESSOR_VERTEX;
- else if (str_match_no_case( &ctx->cur, "GEOM" ))
+ else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
processor = TGSI_PROCESSOR_GEOMETRY;
- else if (str_match_no_case( &ctx->cur, "COMP" ))
+ else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
processor = TGSI_PROCESSOR_COMPUTE;
else {
report_error( ctx, "Unknown header" );
for (i = 0; i < TGSI_FILE_COUNT; i++) {
const char *cur = *pcur;
- if (str_match_no_case( &cur, tgsi_file_names[i] )) {
- if (!is_digit_alpha_underscore( cur )) {
- *pcur = cur;
- *file = i;
- return TRUE;
- }
+ if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
+ *pcur = cur;
+ *file = i;
+ return TRUE;
}
}
return FALSE;
uint ind_file;
int ind_index;
uint ind_comp;
+ uint ind_array;
};
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;
}
dst->Register.Indirect = 1;
dst->Indirect.File = bracket[0].ind_file;
dst->Indirect.Index = bracket[0].ind_index;
- dst->Indirect.SwizzleX = bracket[0].ind_comp;
- dst->Indirect.SwizzleY = bracket[0].ind_comp;
- dst->Indirect.SwizzleZ = bracket[0].ind_comp;
- dst->Indirect.SwizzleW = bracket[0].ind_comp;
+ dst->Indirect.Swizzle = bracket[0].ind_comp;
+ dst->Indirect.ArrayID = bracket[0].ind_array;
}
return TRUE;
}
src->Register.Indirect = 1;
src->Indirect.File = bracket[0].ind_file;
src->Indirect.Index = bracket[0].ind_index;
- src->Indirect.SwizzleX = bracket[0].ind_comp;
- src->Indirect.SwizzleY = bracket[0].ind_comp;
- src->Indirect.SwizzleZ = bracket[0].ind_comp;
- src->Indirect.SwizzleW = bracket[0].ind_comp;
+ src->Indirect.Swizzle = bracket[0].ind_comp;
+ src->Indirect.ArrayID = bracket[0].ind_array;
}
/* Parse optional swizzle.
}
static boolean
-match_inst_mnemonic(const char **pcur,
- const struct tgsi_opcode_info *info)
+match_inst(const char **pcur,
+ unsigned *saturate,
+ const struct tgsi_opcode_info *info)
{
- if (str_match_no_case(pcur, info->mnemonic)) {
+ const char *cur = *pcur;
+
+ /* simple case: the whole string matches the instruction name */
+ if (str_match_nocase_whole(&cur, info->mnemonic)) {
+ *pcur = cur;
+ *saturate = TGSI_SAT_NONE;
return TRUE;
}
+
+ if (str_match_no_case(&cur, info->mnemonic)) {
+ /* the instruction has a suffix, figure it out */
+ if (str_match_nocase_whole(&cur, "_SAT")) {
+ *pcur = cur;
+ *saturate = TGSI_SAT_ZERO_ONE;
+ return TRUE;
+ }
+
+ if (str_match_nocase_whole(&cur, "_SATNV")) {
+ *pcur = cur;
+ *saturate = TGSI_SAT_MINUS_PLUS_ONE;
+ return TRUE;
+ }
+ }
+
return FALSE;
}
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 (match_inst(&cur, &saturate, info)) {
if (info->num_dst + info->num_src + info->is_tex == 0) {
- if (!is_digit_alpha_underscore( cur )) {
- ctx->cur = cur;
- break;
- }
+ ctx->cur = cur;
+ break;
}
else if (*cur == '\0' || eat_white( &cur )) {
ctx->cur = cur;
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 (offsets aren't
+ * actually handled here yet in any case).
+ */
+ inst.Instruction.Texture = 1;
+ inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
+ }
+
/* Parse instruction operands.
*/
for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
uint j;
for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
- if (str_match_no_case( &ctx->cur, tgsi_texture_names[j] )) {
- if (!is_digit_alpha_underscore( ctx->cur )) {
- inst.Instruction.Texture = 1;
- inst.Texture.Texture = j;
- break;
- }
+ 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) {
case TGSI_IMM_INT32:
ret = parse_int(&ctx->cur, &values[i].Int);
break;
+ default:
+ assert(0);
+ ret = FALSE;
+ break;
}
if (!ret) {
const char *cur, *cur2;
uint advance;
boolean is_vs_input;
- boolean is_imm_array;
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
is_vs_input = (file == TGSI_FILE_INPUT &&
ctx->processor == TGSI_PROCESSOR_VERTEX);
- is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY);
cur = ctx->cur;
eat_opt_white( &cur );
+ if (*cur == ',') {
+ cur2 = cur;
+ cur2++;
+ eat_opt_white( &cur2 );
+ if (str_match_nocase_whole( &cur2, "ARRAY" )) {
+ int arrayid;
+ if (*cur2 != '(') {
+ report_error( ctx, "Expected `('" );
+ return FALSE;
+ }
+ cur2++;
+ eat_opt_white( &cur2 );
+ if (!parse_int( &cur2, &arrayid )) {
+ report_error( ctx, "Expected `,'" );
+ return FALSE;
+ }
+ eat_opt_white( &cur2 );
+ if (*cur2 != ')') {
+ report_error( ctx, "Expected `)'" );
+ return FALSE;
+ }
+ cur2++;
+ decl.Declaration.Array = 1;
+ decl.Array.ArrayID = arrayid;
+ ctx->cur = cur = cur2;
+ }
+ }
+
if (*cur == ',' && !is_vs_input) {
uint i, j;
eat_opt_white( &cur );
if (file == TGSI_FILE_RESOURCE) {
for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
- if (str_match_no_case(&cur, tgsi_texture_names[i])) {
- if (!is_digit_alpha_underscore(cur)) {
- decl.Resource.Resource = i;
- break;
- }
+ if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
+ decl.Resource.Resource = i;
+ break;
}
}
if (i == TGSI_TEXTURE_COUNT) {
while (*cur2 == ',') {
cur2++;
eat_opt_white(&cur2);
- if (str_match_no_case(&cur2, "RAW") &&
- !is_digit_alpha_underscore(cur2)) {
+ if (str_match_nocase_whole(&cur2, "RAW")) {
decl.Resource.Raw = 1;
- } else if (str_match_no_case(&cur2, "WR") &&
- !is_digit_alpha_underscore(cur2)) {
+ } else if (str_match_nocase_whole(&cur2, "WR")) {
decl.Resource.Writable = 1;
} else {
} else if (file == TGSI_FILE_SAMPLER_VIEW) {
for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
- if (str_match_no_case(&cur, tgsi_texture_names[i])) {
- if (!is_digit_alpha_underscore(cur)) {
- decl.SamplerView.Resource = i;
- break;
- }
+ if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
+ decl.SamplerView.Resource = i;
+ break;
}
}
if (i == TGSI_TEXTURE_COUNT) {
eat_opt_white( &cur );
for (j = 0; j < 4; ++j) {
for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
- if (str_match_no_case(&cur, tgsi_type_names[i])) {
- if (!is_digit_alpha_underscore(cur)) {
- switch (j) {
- case 0:
- decl.SamplerView.ReturnTypeX = i;
- break;
- case 1:
- decl.SamplerView.ReturnTypeY = i;
- break;
- case 2:
- decl.SamplerView.ReturnTypeZ = i;
- break;
- case 3:
- decl.SamplerView.ReturnTypeW = i;
- break;
- default:
- assert(0);
- }
+ if (str_match_nocase_whole(&cur, tgsi_type_names[i])) {
+ switch (j) {
+ case 0:
+ decl.SamplerView.ReturnTypeX = i;
+ break;
+ case 1:
+ decl.SamplerView.ReturnTypeY = i;
break;
+ case 2:
+ decl.SamplerView.ReturnTypeZ = i;
+ break;
+ case 3:
+ decl.SamplerView.ReturnTypeW = i;
+ break;
+ default:
+ assert(0);
}
+ break;
}
}
if (i == PIPE_TYPE_COUNT) {
}
ctx->cur = cur;
} else {
- if (str_match_no_case(&cur, "LOCAL") &&
- !is_digit_alpha_underscore(cur)) {
+ if (str_match_nocase_whole(&cur, "LOCAL")) {
decl.Declaration.Local = 1;
ctx->cur = cur;
}
eat_opt_white( &cur );
for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
- if (str_match_no_case( &cur, tgsi_semantic_names[i] )) {
+ if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
uint index;
- if (is_digit_alpha_underscore( cur ))
- continue;
cur2 = cur;
eat_opt_white( &cur2 );
if (*cur2 == '[') {
}
}
}
- } else if (is_imm_array) {
- unsigned i;
- union tgsi_immediate_data *vals_itr;
- /* we have our immediate data */
- if (*cur != '{') {
- report_error( ctx, "Immediate array without data" );
- return FALSE;
- }
- ++cur;
- ctx->cur = cur;
-
- decl.ImmediateData.u =
- MALLOC(sizeof(union tgsi_immediate_data) * 4 *
- (decl.Range.Last + 1));
- vals_itr = decl.ImmediateData.u;
- for (i = 0; i <= decl.Range.Last; ++i) {
- if (!parse_immediate_data(ctx, TGSI_IMM_FLOAT32, vals_itr)) {
- FREE(decl.ImmediateData.u);
- return FALSE;
- }
- vals_itr += 4;
- eat_opt_white( &ctx->cur );
- if (*ctx->cur != ',') {
- if (i != decl.Range.Last) {
- report_error( ctx, "Not enough data in immediate array!" );
- FREE(decl.ImmediateData.u);
- return FALSE;
- }
- } else
- ++ctx->cur;
- }
- eat_opt_white( &ctx->cur );
- if (*ctx->cur != '}') {
- FREE(decl.ImmediateData.u);
- report_error( ctx, "Immediate array data missing closing '}'" );
- return FALSE;
- }
- ++ctx->cur;
}
cur = ctx->cur;
cur++;
eat_opt_white( &cur );
for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
- if (str_match_no_case( &cur, tgsi_interpolate_names[i] )) {
- if (is_digit_alpha_underscore( cur ))
- continue;
+ if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
decl.Declaration.Interpolate = 1;
decl.Interp.Interpolate = i;
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
- if (is_imm_array)
- FREE(decl.ImmediateData.u);
-
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
uint advance;
int type;
+ if (*ctx->cur == '[') {
+ uint uindex;
+
+ ++ctx->cur;
+
+ eat_opt_white( &ctx->cur );
+ if (!parse_uint( &ctx->cur, &uindex )) {
+ report_error( ctx, "Expected literal unsigned integer" );
+ return FALSE;
+ }
+
+ if (uindex != ctx->num_immediates) {
+ report_error( ctx, "Immediates must be sorted" );
+ return FALSE;
+ }
+
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != ']') {
+ report_error( ctx, "Expected `]'" );
+ return FALSE;
+ }
+
+ ctx->cur++;
+ }
+
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
for (type = 0; type < Elements(tgsi_immediate_type_names); ++type) {
- if (str_match_no_case(&ctx->cur, tgsi_immediate_type_names[type]) &&
- !is_digit_alpha_underscore(ctx->cur))
+ if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
break;
}
if (type == Elements(tgsi_immediate_type_names)) {
return FALSE;
ctx->tokens_cur += advance;
+ ctx->num_immediates++;
+
return TRUE;
}
for (i = 0; i < PIPE_PRIM_MAX; i++) {
const char *cur = *pcur;
- if (str_match_no_case( &cur, tgsi_primitive_names[i])) {
+ if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
*primitive = i;
*pcur = cur;
return TRUE;
for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
const char *cur = *pcur;
- if (str_match_no_case( &cur, tgsi_fs_coord_origin_names[i])) {
+ if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
*fs_coord_origin = i;
*pcur = cur;
return TRUE;
for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
const char *cur = *pcur;
- if (str_match_no_case( &cur, tgsi_fs_coord_pixel_center_names[i])) {
+ if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
*fs_coord_pixel_center = i;
*pcur = cur;
return TRUE;
if (!parse_instruction( ctx, TRUE ))
return FALSE;
}
- else if (str_match_no_case( &ctx->cur, "DCL" )) {
+ else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
if (!parse_declaration( ctx ))
return FALSE;
}
- else if (str_match_no_case( &ctx->cur, "IMM" )) {
+ else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
if (!parse_immediate( ctx ))
return FALSE;
}
- else if (str_match_no_case( &ctx->cur, "PROPERTY" )) {
+ else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
if (!parse_property( ctx ))
return FALSE;
}
struct tgsi_token *tokens,
uint num_tokens )
{
- struct translate_ctx ctx;
+ struct translate_ctx ctx = {0};
ctx.text = text;
ctx.cur = text;