tgsi: Parse DCL statements.

This commit is contained in:
Michal Krol
2008-07-13 11:37:36 +02:00
parent bd3b47590e
commit ee647b9020
+256 -74
View File
@@ -49,6 +49,21 @@ static boolean is_digit_alpha_underscore( const char *cur )
return is_digit( cur ) || is_alpha_underscore( cur );
}
static boolean str_match_no_case( const char **pcur, const char *str )
{
const char *cur = *pcur;
while (*str != '\0' && *str == toupper( *cur )) {
str++;
cur++;
}
if (*str == '\0') {
*pcur = cur;
return TRUE;
}
return FALSE;
}
/* Eat zero or more whitespaces.
*/
static void eat_opt_white( const char **pcur )
@@ -110,28 +125,14 @@ static boolean parse_header( struct translate_ctx *ctx )
{
uint processor;
if (ctx->cur[0] == 'F' && ctx->cur[1] == 'R' && ctx->cur[2] == 'A' && ctx->cur[3] == 'G') {
ctx->cur += 4;
if (str_match_no_case( &ctx->cur, "FRAG1.1" ))
processor = TGSI_PROCESSOR_FRAGMENT;
}
else if (ctx->cur[0] == 'V' && ctx->cur[1] == 'E' && ctx->cur[2] == 'R' && ctx->cur[3] == 'T') {
ctx->cur += 4;
else if (str_match_no_case( &ctx->cur, "VERT1.1" ))
processor = TGSI_PROCESSOR_VERTEX;
}
else if (ctx->cur[0] == 'G' && ctx->cur[1] == 'E' && ctx->cur[2] == 'O' && ctx->cur[3] == 'M') {
ctx->cur += 4;
else if (str_match_no_case( &ctx->cur, "GEOM1.1" ))
processor = TGSI_PROCESSOR_GEOMETRY;
}
else {
report_error( ctx, "Unknown processor type" );
return FALSE;
}
if (ctx->cur[0] == '1' && ctx->cur[1] == '.' && ctx->cur[2] == '1') {
ctx->cur += 3;
}
else {
report_error( ctx, "Unknown version" );
report_error( ctx, "Unknown header" );
return FALSE;
}
@@ -187,16 +188,13 @@ parse_file(
for (i = 0; i < TGSI_FILE_COUNT; i++) {
const char *cur = ctx->cur;
const char *name = file_names[i];
while (*name != '\0' && *name == toupper( *cur )) {
name++;
cur++;
}
if (*name == '\0' && !is_digit_alpha_underscore( cur )) {
ctx->cur = cur;
*file = i;
return TRUE;
if (str_match_no_case( &cur, file_names[i] )) {
if (!is_digit_alpha_underscore( cur )) {
ctx->cur = cur;
*file = i;
return TRUE;
}
}
}
report_error( ctx, "Unknown register file" );
@@ -204,7 +202,53 @@ parse_file(
}
static boolean
parse_register(
parse_opt_writemask(
struct translate_ctx *ctx,
uint *writemask )
{
const char *cur;
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == '.') {
cur++;
*writemask = TGSI_WRITEMASK_NONE;
eat_opt_white( &cur );
if (toupper( *cur ) == 'X') {
cur++;
*writemask |= TGSI_WRITEMASK_X;
}
if (toupper( *cur ) == 'Y') {
cur++;
*writemask |= TGSI_WRITEMASK_Y;
}
if (toupper( *cur ) == 'Z') {
cur++;
*writemask |= TGSI_WRITEMASK_Z;
}
if (toupper( *cur ) == 'W') {
cur++;
*writemask |= TGSI_WRITEMASK_W;
}
if (*writemask == TGSI_WRITEMASK_NONE) {
report_error( ctx, "Writemask expected" );
return FALSE;
}
ctx->cur = cur;
}
else {
*writemask = TGSI_WRITEMASK_XYZW;
}
return TRUE;
}
/* Parse register part common for decls and operands.
* <register_prefix> ::= <file> `[' <index>
*/
static boolean
parse_register_prefix(
struct translate_ctx *ctx,
uint *file,
uint *index )
@@ -222,6 +266,20 @@ parse_register(
report_error( ctx, "Expected literal integer" );
return FALSE;
}
return TRUE;
}
/* Parse register operand.
* <register> ::= <register_prefix> `]'
*/
static boolean
parse_register(
struct translate_ctx *ctx,
uint *file,
uint *index )
{
if (!parse_register_prefix( ctx, file, index ))
return FALSE;
eat_opt_white( &ctx->cur );
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]'" );
@@ -232,54 +290,55 @@ parse_register(
return TRUE;
}
/* Parse register declaration.
* <register> ::= <register_prefix> `]' | <register_prefix> `..' <index> `]'
*/
static boolean
parse_register_dcl(
struct translate_ctx *ctx,
uint *file,
uint *first,
uint *last )
{
if (!parse_register_prefix( ctx, file, first ))
return FALSE;
eat_opt_white( &ctx->cur );
if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
ctx->cur += 2;
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, last )) {
report_error( ctx, "Expected literal integer" );
return FALSE;
}
eat_opt_white( &ctx->cur );
}
else {
*last = *first;
}
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]' or `..'" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
static boolean
parse_dst_operand(
struct translate_ctx *ctx,
struct tgsi_full_dst_register *dst )
{
const char *cur;
uint file;
uint index;
uint writemask;
if (!parse_register( ctx, &file, &index ))
return FALSE;
if (!parse_opt_writemask( ctx, &writemask ))
return FALSE;
dst->DstRegister.File = file;
dst->DstRegister.Index = index;
/* Parse optional write mask.
*/
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == '.') {
uint writemask = TGSI_WRITEMASK_NONE;
cur++;
eat_opt_white( &cur );
if (toupper( *cur ) == 'X') {
cur++;
writemask |= TGSI_WRITEMASK_X;
}
if (toupper( *cur ) == 'Y') {
cur++;
writemask |= TGSI_WRITEMASK_Y;
}
if (toupper( *cur ) == 'Z') {
cur++;
writemask |= TGSI_WRITEMASK_Z;
}
if (toupper( *cur ) == 'W') {
cur++;
writemask |= TGSI_WRITEMASK_W;
}
if (writemask == TGSI_WRITEMASK_NONE) {
report_error( ctx, "Writemask expected" );
return FALSE;
}
dst->DstRegister.WriteMask = writemask;
ctx->cur = cur;
}
dst->DstRegister.WriteMask = writemask;
return TRUE;
}
@@ -478,15 +537,10 @@ static boolean parse_instruction( struct translate_ctx *ctx )
eat_opt_white( &ctx->cur );
for (i = 0; i < TGSI_OPCODE_LAST; i++) {
const char *cur = ctx->cur;
const char *op = opcode_info[i].mnemonic;
while (*op != '\0' && *op == toupper( *cur )) {
op++;
cur++;
}
if (*op == '\0') {
if (str_match_no_case( &cur, opcode_info[i].mnemonic )) {
/* TODO: _SAT suffix */
if (*cur == '\0' || eat_white( &cur )) {
if (eat_white( &cur )) {
ctx->cur = cur;
break;
}
@@ -525,7 +579,6 @@ static boolean parse_instruction( struct translate_ctx *ctx )
return FALSE;
}
}
eat_opt_white( &ctx->cur );
advance = tgsi_build_full_instruction(
&inst,
@@ -539,22 +592,151 @@ static boolean parse_instruction( struct translate_ctx *ctx )
return TRUE;
}
static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
{
"POSITION",
"COLOR",
"BCOLOR",
"FOG",
"PSIZE",
"GENERIC",
"NORMAL"
};
static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
{
"CONSTANT",
"LINEAR",
"PERSPECTIVE"
};
static boolean parse_declaration( struct translate_ctx *ctx )
{
struct tgsi_full_declaration decl;
uint file;
uint first;
uint last;
uint writemask;
const char *cur;
uint advance;
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
if (!parse_register_dcl( ctx, &file, &first, &last ))
return FALSE;
if (!parse_opt_writemask( ctx, &writemask ))
return FALSE;
decl = tgsi_default_full_declaration();
decl.Declaration.File = file;
decl.Declaration.UsageMask = writemask;
decl.DeclarationRange.First = first;
decl.DeclarationRange.Last = last;
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == ',') {
uint i;
cur++;
eat_opt_white( &cur );
for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
if (str_match_no_case( &cur, semantic_names[i] )) {
const char *cur2 = cur;
uint index;
if (is_digit_alpha_underscore( cur ))
continue;
eat_opt_white( &cur2 );
if (*cur2 == '[') {
cur2++;
eat_opt_white( &cur2 );
if (!parse_uint( &cur2, &index )) {
report_error( ctx, "Expected literal integer" );
return FALSE;
}
eat_opt_white( &cur2 );
if (*cur2 != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
cur2++;
decl.Semantic.SemanticIndex = index;
cur = cur2;
}
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = i;
ctx->cur = cur;
break;
}
}
}
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == ',') {
uint i;
cur++;
eat_opt_white( &cur );
for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
if (str_match_no_case( &cur, interpolate_names[i] )) {
if (is_digit_alpha_underscore( cur ))
continue;
decl.Declaration.Interpolate = i;
ctx->cur = cur;
break;
}
}
if (i == TGSI_INTERPOLATE_COUNT) {
report_error( ctx, "Expected semantic or interpolate attribute" );
return FALSE;
}
}
advance = tgsi_build_full_declaration(
&decl,
ctx->tokens_cur,
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
return TRUE;
}
static boolean translate( struct translate_ctx *ctx )
{
eat_opt_white( &ctx->cur );
if (!parse_header( ctx ))
return FALSE;
eat_white( &ctx->cur );
while (*ctx->cur != '\0') {
uint label_val = 0;
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
if (parse_label( ctx, &label_val )) {
if (!parse_instruction( ctx ))
return FALSE;
}
else if (str_match_no_case( &ctx->cur, "DCL" )) {
if (!parse_declaration( ctx ))
return FALSE;
}
else {
report_error( ctx, "Instruction expected" );
report_error( ctx, "Expected `DCL' or a label" );
return FALSE;
}
}