1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2008 VMware, Inc. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg#include "util/u_debug.h" 29848b8605Smrg#include "util/u_memory.h" 30848b8605Smrg#include "util/u_prim.h" 31848b8605Smrg#include "pipe/p_defines.h" 32848b8605Smrg#include "util/u_inlines.h" 33848b8605Smrg#include "tgsi_text.h" 34848b8605Smrg#include "tgsi_build.h" 35848b8605Smrg#include "tgsi_info.h" 36848b8605Smrg#include "tgsi_parse.h" 37848b8605Smrg#include "tgsi_sanity.h" 38848b8605Smrg#include "tgsi_strings.h" 39848b8605Smrg#include "tgsi_util.h" 40848b8605Smrg#include "tgsi_dump.h" 41848b8605Smrg 42848b8605Smrgstatic boolean is_alpha_underscore( const char *cur ) 43848b8605Smrg{ 44848b8605Smrg return 45848b8605Smrg (*cur >= 'a' && *cur <= 'z') || 46848b8605Smrg (*cur >= 'A' && *cur <= 'Z') || 47848b8605Smrg *cur == '_'; 48848b8605Smrg} 49848b8605Smrg 50848b8605Smrgstatic boolean is_digit( const char *cur ) 51848b8605Smrg{ 52848b8605Smrg return *cur >= '0' && *cur <= '9'; 53848b8605Smrg} 54848b8605Smrg 55848b8605Smrgstatic boolean is_digit_alpha_underscore( const char *cur ) 56848b8605Smrg{ 57848b8605Smrg return is_digit( cur ) || is_alpha_underscore( cur ); 58848b8605Smrg} 59848b8605Smrg 60848b8605Smrgstatic char uprcase( char c ) 61848b8605Smrg{ 62848b8605Smrg if (c >= 'a' && c <= 'z') 63848b8605Smrg return c + 'A' - 'a'; 64848b8605Smrg return c; 65848b8605Smrg} 66848b8605Smrg 67848b8605Smrg/* 68848b8605Smrg * Ignore case of str1 and assume str1 is already uppercase. 69848b8605Smrg * Return TRUE iff str1 and str2 are equal. 70848b8605Smrg */ 71848b8605Smrgstatic int 72848b8605Smrgstreq_nocase_uprcase(const char *str1, 73848b8605Smrg const char *str2) 74848b8605Smrg{ 75848b8605Smrg while (*str1 && *str2) { 76848b8605Smrg if (*str1 != uprcase(*str2)) 77848b8605Smrg return FALSE; 78848b8605Smrg str1++; 79848b8605Smrg str2++; 80848b8605Smrg } 81848b8605Smrg return *str1 == 0 && *str2 == 0; 82848b8605Smrg} 83848b8605Smrg 84848b8605Smrg/* Return TRUE if both strings match. 85848b8605Smrg * The second string is terminated by zero. 86848b8605Smrg * The pointer to the first string is moved at end of the read word 87848b8605Smrg * on success. 88848b8605Smrg */ 89848b8605Smrgstatic boolean str_match_no_case( const char **pcur, const char *str ) 90848b8605Smrg{ 91848b8605Smrg const char *cur = *pcur; 92848b8605Smrg 93848b8605Smrg while (*str != '\0' && *str == uprcase( *cur )) { 94848b8605Smrg str++; 95848b8605Smrg cur++; 96848b8605Smrg } 97848b8605Smrg if (*str == '\0') { 98848b8605Smrg *pcur = cur; 99848b8605Smrg return TRUE; 100848b8605Smrg } 101848b8605Smrg return FALSE; 102848b8605Smrg} 103848b8605Smrg 104848b8605Smrg/* Return TRUE if both strings match. 105848b8605Smrg * The first string is be terminated by a non-digit non-letter non-underscore 106848b8605Smrg * character, the second string is terminated by zero. 107848b8605Smrg * The pointer to the first string is moved at end of the read word 108848b8605Smrg * on success. 109848b8605Smrg */ 110848b8605Smrgstatic boolean str_match_nocase_whole( const char **pcur, const char *str ) 111848b8605Smrg{ 112848b8605Smrg const char *cur = *pcur; 113848b8605Smrg 114848b8605Smrg if (str_match_no_case(&cur, str) && 115848b8605Smrg !is_digit_alpha_underscore(cur)) { 116848b8605Smrg *pcur = cur; 117848b8605Smrg return TRUE; 118848b8605Smrg } 119848b8605Smrg return FALSE; 120848b8605Smrg} 121848b8605Smrg 122b8e80941Smrg/* Return the array index that matches starting at *pcur, where the string at 123b8e80941Smrg * *pcur is terminated by a non-digit non-letter non-underscore. 124b8e80941Smrg * Returns -1 if no match is found. 125b8e80941Smrg * 126b8e80941Smrg * On success, the pointer to the first string is moved to the end of the read 127b8e80941Smrg * word. 128b8e80941Smrg */ 129b8e80941Smrgstatic int str_match_name_from_array(const char **pcur, 130b8e80941Smrg const char * const *array, 131b8e80941Smrg unsigned array_size) 132b8e80941Smrg{ 133b8e80941Smrg for (unsigned j = 0; j < array_size; ++j) { 134b8e80941Smrg if (str_match_nocase_whole(pcur, array[j])) 135b8e80941Smrg return j; 136b8e80941Smrg } 137b8e80941Smrg return -1; 138b8e80941Smrg} 139b8e80941Smrg 140b8e80941Smrg/* Return the format corresponding to the name at *pcur. 141b8e80941Smrg * Returns -1 if there is no format name. 142b8e80941Smrg * 143b8e80941Smrg * On success, the pointer to the string is moved to the end of the read format 144b8e80941Smrg * name. 145b8e80941Smrg */ 146b8e80941Smrgstatic int str_match_format(const char **pcur) 147b8e80941Smrg{ 148b8e80941Smrg for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) { 149b8e80941Smrg const struct util_format_description *desc = 150b8e80941Smrg util_format_description(i); 151b8e80941Smrg if (desc && str_match_nocase_whole(pcur, desc->name)) { 152b8e80941Smrg return i; 153b8e80941Smrg } 154b8e80941Smrg } 155b8e80941Smrg return -1; 156b8e80941Smrg} 157b8e80941Smrg 158848b8605Smrg/* Eat zero or more whitespaces. 159848b8605Smrg */ 160848b8605Smrgstatic void eat_opt_white( const char **pcur ) 161848b8605Smrg{ 162848b8605Smrg while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n') 163848b8605Smrg (*pcur)++; 164848b8605Smrg} 165848b8605Smrg 166848b8605Smrg/* Eat one or more whitespaces. 167848b8605Smrg * Return TRUE if at least one whitespace eaten. 168848b8605Smrg */ 169848b8605Smrgstatic boolean eat_white( const char **pcur ) 170848b8605Smrg{ 171848b8605Smrg const char *cur = *pcur; 172848b8605Smrg 173848b8605Smrg eat_opt_white( pcur ); 174848b8605Smrg return *pcur > cur; 175848b8605Smrg} 176848b8605Smrg 177848b8605Smrg/* Parse unsigned integer. 178848b8605Smrg * No checks for overflow. 179848b8605Smrg */ 180848b8605Smrgstatic boolean parse_uint( const char **pcur, uint *val ) 181848b8605Smrg{ 182848b8605Smrg const char *cur = *pcur; 183848b8605Smrg 184848b8605Smrg if (is_digit( cur )) { 185848b8605Smrg *val = *cur++ - '0'; 186848b8605Smrg while (is_digit( cur )) 187848b8605Smrg *val = *val * 10 + *cur++ - '0'; 188848b8605Smrg *pcur = cur; 189848b8605Smrg return TRUE; 190848b8605Smrg } 191848b8605Smrg return FALSE; 192848b8605Smrg} 193848b8605Smrg 194848b8605Smrgstatic boolean parse_int( const char **pcur, int *val ) 195848b8605Smrg{ 196848b8605Smrg const char *cur = *pcur; 197848b8605Smrg int sign = (*cur == '-' ? -1 : 1); 198848b8605Smrg 199848b8605Smrg if (*cur == '+' || *cur == '-') 200848b8605Smrg cur++; 201848b8605Smrg 202848b8605Smrg if (parse_uint(&cur, (uint *)val)) { 203848b8605Smrg *val *= sign; 204848b8605Smrg *pcur = cur; 205848b8605Smrg return TRUE; 206848b8605Smrg } 207848b8605Smrg 208848b8605Smrg return FALSE; 209848b8605Smrg} 210848b8605Smrg 211b8e80941Smrgstatic boolean parse_identifier( const char **pcur, char *ret, size_t len ) 212848b8605Smrg{ 213848b8605Smrg const char *cur = *pcur; 214b8e80941Smrg size_t i = 0; 215848b8605Smrg if (is_alpha_underscore( cur )) { 216848b8605Smrg ret[i++] = *cur++; 217b8e80941Smrg while (is_alpha_underscore( cur ) || is_digit( cur )) { 218b8e80941Smrg if (i == len - 1) 219b8e80941Smrg return FALSE; 220848b8605Smrg ret[i++] = *cur++; 221b8e80941Smrg } 222848b8605Smrg ret[i++] = '\0'; 223848b8605Smrg *pcur = cur; 224848b8605Smrg return TRUE; 225848b8605Smrg } 226848b8605Smrg return FALSE; 227848b8605Smrg} 228848b8605Smrg 229848b8605Smrg/* Parse floating point. 230848b8605Smrg */ 231848b8605Smrgstatic boolean parse_float( const char **pcur, float *val ) 232848b8605Smrg{ 233848b8605Smrg const char *cur = *pcur; 234848b8605Smrg boolean integral_part = FALSE; 235848b8605Smrg boolean fractional_part = FALSE; 236848b8605Smrg 237b8e80941Smrg if (*cur == '0' && *(cur + 1) == 'x') { 238b8e80941Smrg union fi fi; 239b8e80941Smrg fi.ui = strtoul(cur, NULL, 16); 240b8e80941Smrg *val = fi.f; 241b8e80941Smrg cur += 10; 242b8e80941Smrg goto out; 243b8e80941Smrg } 244848b8605Smrg 245b8e80941Smrg *val = (float) atof( cur ); 246848b8605Smrg if (*cur == '-' || *cur == '+') 247848b8605Smrg cur++; 248848b8605Smrg if (is_digit( cur )) { 249848b8605Smrg cur++; 250848b8605Smrg integral_part = TRUE; 251848b8605Smrg while (is_digit( cur )) 252848b8605Smrg cur++; 253848b8605Smrg } 254848b8605Smrg if (*cur == '.') { 255848b8605Smrg cur++; 256848b8605Smrg if (is_digit( cur )) { 257848b8605Smrg cur++; 258848b8605Smrg fractional_part = TRUE; 259848b8605Smrg while (is_digit( cur )) 260848b8605Smrg cur++; 261848b8605Smrg } 262848b8605Smrg } 263848b8605Smrg if (!integral_part && !fractional_part) 264848b8605Smrg return FALSE; 265848b8605Smrg if (uprcase( *cur ) == 'E') { 266848b8605Smrg cur++; 267848b8605Smrg if (*cur == '-' || *cur == '+') 268848b8605Smrg cur++; 269848b8605Smrg if (is_digit( cur )) { 270848b8605Smrg cur++; 271848b8605Smrg while (is_digit( cur )) 272848b8605Smrg cur++; 273848b8605Smrg } 274848b8605Smrg else 275848b8605Smrg return FALSE; 276848b8605Smrg } 277b8e80941Smrg 278b8e80941Smrgout: 279848b8605Smrg *pcur = cur; 280848b8605Smrg return TRUE; 281848b8605Smrg} 282848b8605Smrg 283b8e80941Smrgstatic boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1) 284b8e80941Smrg{ 285b8e80941Smrg const char *cur = *pcur; 286b8e80941Smrg union { 287b8e80941Smrg double dval; 288b8e80941Smrg uint32_t uval[2]; 289b8e80941Smrg } v; 290b8e80941Smrg 291b8e80941Smrg v.dval = strtod(cur, (char**)pcur); 292b8e80941Smrg if (*pcur == cur) 293b8e80941Smrg return FALSE; 294b8e80941Smrg 295b8e80941Smrg *val0 = v.uval[0]; 296b8e80941Smrg *val1 = v.uval[1]; 297b8e80941Smrg 298b8e80941Smrg return TRUE; 299b8e80941Smrg} 300b8e80941Smrg 301b8e80941Smrgstatic boolean parse_int64( const char **pcur, uint32_t *val0, uint32_t *val1) 302b8e80941Smrg{ 303b8e80941Smrg const char *cur = *pcur; 304b8e80941Smrg union { 305b8e80941Smrg int64_t i64val; 306b8e80941Smrg uint32_t uval[2]; 307b8e80941Smrg } v; 308b8e80941Smrg 309b8e80941Smrg v.i64val = strtoll(cur, (char**)pcur, 0); 310b8e80941Smrg if (*pcur == cur) 311b8e80941Smrg return FALSE; 312b8e80941Smrg 313b8e80941Smrg *val0 = v.uval[0]; 314b8e80941Smrg *val1 = v.uval[1]; 315b8e80941Smrg 316b8e80941Smrg return TRUE; 317b8e80941Smrg} 318b8e80941Smrg 319b8e80941Smrgstatic boolean parse_uint64( const char **pcur, uint32_t *val0, uint32_t *val1) 320b8e80941Smrg{ 321b8e80941Smrg const char *cur = *pcur; 322b8e80941Smrg union { 323b8e80941Smrg uint64_t u64val; 324b8e80941Smrg uint32_t uval[2]; 325b8e80941Smrg } v; 326b8e80941Smrg 327b8e80941Smrg v.u64val = strtoull(cur, (char**)pcur, 0); 328b8e80941Smrg if (*pcur == cur) 329b8e80941Smrg return FALSE; 330b8e80941Smrg 331b8e80941Smrg *val0 = v.uval[0]; 332b8e80941Smrg *val1 = v.uval[1]; 333b8e80941Smrg 334b8e80941Smrg return TRUE; 335b8e80941Smrg} 336b8e80941Smrg 337848b8605Smrgstruct translate_ctx 338848b8605Smrg{ 339848b8605Smrg const char *text; 340848b8605Smrg const char *cur; 341848b8605Smrg struct tgsi_token *tokens; 342848b8605Smrg struct tgsi_token *tokens_cur; 343848b8605Smrg struct tgsi_token *tokens_end; 344848b8605Smrg struct tgsi_header *header; 345848b8605Smrg unsigned processor : 4; 346b8e80941Smrg unsigned implied_array_size : 6; 347848b8605Smrg unsigned num_immediates; 348848b8605Smrg}; 349848b8605Smrg 350848b8605Smrgstatic void report_error( struct translate_ctx *ctx, const char *msg ) 351848b8605Smrg{ 352848b8605Smrg int line = 1; 353848b8605Smrg int column = 1; 354848b8605Smrg const char *itr = ctx->text; 355848b8605Smrg 356848b8605Smrg while (itr != ctx->cur) { 357848b8605Smrg if (*itr == '\n') { 358848b8605Smrg column = 1; 359848b8605Smrg ++line; 360848b8605Smrg } 361848b8605Smrg ++column; 362848b8605Smrg ++itr; 363848b8605Smrg } 364848b8605Smrg 365848b8605Smrg debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column ); 366848b8605Smrg} 367848b8605Smrg 368848b8605Smrg/* Parse shader header. 369848b8605Smrg * Return TRUE for one of the following headers. 370848b8605Smrg * FRAG 371848b8605Smrg * GEOM 372848b8605Smrg * VERT 373848b8605Smrg */ 374848b8605Smrgstatic boolean parse_header( struct translate_ctx *ctx ) 375848b8605Smrg{ 376848b8605Smrg uint processor; 377848b8605Smrg 378848b8605Smrg if (str_match_nocase_whole( &ctx->cur, "FRAG" )) 379b8e80941Smrg processor = PIPE_SHADER_FRAGMENT; 380848b8605Smrg else if (str_match_nocase_whole( &ctx->cur, "VERT" )) 381b8e80941Smrg processor = PIPE_SHADER_VERTEX; 382848b8605Smrg else if (str_match_nocase_whole( &ctx->cur, "GEOM" )) 383b8e80941Smrg processor = PIPE_SHADER_GEOMETRY; 384b8e80941Smrg else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" )) 385b8e80941Smrg processor = PIPE_SHADER_TESS_CTRL; 386b8e80941Smrg else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" )) 387b8e80941Smrg processor = PIPE_SHADER_TESS_EVAL; 388848b8605Smrg else if (str_match_nocase_whole( &ctx->cur, "COMP" )) 389b8e80941Smrg processor = PIPE_SHADER_COMPUTE; 390848b8605Smrg else { 391848b8605Smrg report_error( ctx, "Unknown header" ); 392848b8605Smrg return FALSE; 393848b8605Smrg } 394848b8605Smrg 395848b8605Smrg if (ctx->tokens_cur >= ctx->tokens_end) 396848b8605Smrg return FALSE; 397848b8605Smrg ctx->header = (struct tgsi_header *) ctx->tokens_cur++; 398848b8605Smrg *ctx->header = tgsi_build_header(); 399848b8605Smrg 400848b8605Smrg if (ctx->tokens_cur >= ctx->tokens_end) 401848b8605Smrg return FALSE; 402848b8605Smrg *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header ); 403848b8605Smrg ctx->processor = processor; 404848b8605Smrg 405848b8605Smrg return TRUE; 406848b8605Smrg} 407848b8605Smrg 408848b8605Smrgstatic boolean parse_label( struct translate_ctx *ctx, uint *val ) 409848b8605Smrg{ 410848b8605Smrg const char *cur = ctx->cur; 411848b8605Smrg 412848b8605Smrg if (parse_uint( &cur, val )) { 413848b8605Smrg eat_opt_white( &cur ); 414848b8605Smrg if (*cur == ':') { 415848b8605Smrg cur++; 416848b8605Smrg ctx->cur = cur; 417848b8605Smrg return TRUE; 418848b8605Smrg } 419848b8605Smrg } 420848b8605Smrg return FALSE; 421848b8605Smrg} 422848b8605Smrg 423848b8605Smrgstatic boolean 424848b8605Smrgparse_file( const char **pcur, uint *file ) 425848b8605Smrg{ 426848b8605Smrg uint i; 427848b8605Smrg 428848b8605Smrg for (i = 0; i < TGSI_FILE_COUNT; i++) { 429848b8605Smrg const char *cur = *pcur; 430848b8605Smrg 431848b8605Smrg if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) { 432848b8605Smrg *pcur = cur; 433848b8605Smrg *file = i; 434848b8605Smrg return TRUE; 435848b8605Smrg } 436848b8605Smrg } 437848b8605Smrg return FALSE; 438848b8605Smrg} 439848b8605Smrg 440848b8605Smrgstatic boolean 441848b8605Smrgparse_opt_writemask( 442848b8605Smrg struct translate_ctx *ctx, 443848b8605Smrg uint *writemask ) 444848b8605Smrg{ 445848b8605Smrg const char *cur; 446848b8605Smrg 447848b8605Smrg cur = ctx->cur; 448848b8605Smrg eat_opt_white( &cur ); 449848b8605Smrg if (*cur == '.') { 450848b8605Smrg cur++; 451848b8605Smrg *writemask = TGSI_WRITEMASK_NONE; 452848b8605Smrg eat_opt_white( &cur ); 453848b8605Smrg if (uprcase( *cur ) == 'X') { 454848b8605Smrg cur++; 455848b8605Smrg *writemask |= TGSI_WRITEMASK_X; 456848b8605Smrg } 457848b8605Smrg if (uprcase( *cur ) == 'Y') { 458848b8605Smrg cur++; 459848b8605Smrg *writemask |= TGSI_WRITEMASK_Y; 460848b8605Smrg } 461848b8605Smrg if (uprcase( *cur ) == 'Z') { 462848b8605Smrg cur++; 463848b8605Smrg *writemask |= TGSI_WRITEMASK_Z; 464848b8605Smrg } 465848b8605Smrg if (uprcase( *cur ) == 'W') { 466848b8605Smrg cur++; 467848b8605Smrg *writemask |= TGSI_WRITEMASK_W; 468848b8605Smrg } 469848b8605Smrg 470848b8605Smrg if (*writemask == TGSI_WRITEMASK_NONE) { 471848b8605Smrg report_error( ctx, "Writemask expected" ); 472848b8605Smrg return FALSE; 473848b8605Smrg } 474848b8605Smrg 475848b8605Smrg ctx->cur = cur; 476848b8605Smrg } 477848b8605Smrg else { 478848b8605Smrg *writemask = TGSI_WRITEMASK_XYZW; 479848b8605Smrg } 480848b8605Smrg return TRUE; 481848b8605Smrg} 482848b8605Smrg 483848b8605Smrg 484848b8605Smrg/* <register_file_bracket> ::= <file> `[' 485848b8605Smrg */ 486848b8605Smrgstatic boolean 487848b8605Smrgparse_register_file_bracket( 488848b8605Smrg struct translate_ctx *ctx, 489848b8605Smrg uint *file ) 490848b8605Smrg{ 491848b8605Smrg if (!parse_file( &ctx->cur, file )) { 492848b8605Smrg report_error( ctx, "Unknown register file" ); 493848b8605Smrg return FALSE; 494848b8605Smrg } 495848b8605Smrg eat_opt_white( &ctx->cur ); 496848b8605Smrg if (*ctx->cur != '[') { 497848b8605Smrg report_error( ctx, "Expected `['" ); 498848b8605Smrg return FALSE; 499848b8605Smrg } 500848b8605Smrg ctx->cur++; 501848b8605Smrg return TRUE; 502848b8605Smrg} 503848b8605Smrg 504848b8605Smrg/* <register_file_bracket_index> ::= <register_file_bracket> <uint> 505848b8605Smrg */ 506848b8605Smrgstatic boolean 507848b8605Smrgparse_register_file_bracket_index( 508848b8605Smrg struct translate_ctx *ctx, 509848b8605Smrg uint *file, 510848b8605Smrg int *index ) 511848b8605Smrg{ 512848b8605Smrg uint uindex; 513848b8605Smrg 514848b8605Smrg if (!parse_register_file_bracket( ctx, file )) 515848b8605Smrg return FALSE; 516848b8605Smrg eat_opt_white( &ctx->cur ); 517848b8605Smrg if (!parse_uint( &ctx->cur, &uindex )) { 518848b8605Smrg report_error( ctx, "Expected literal unsigned integer" ); 519848b8605Smrg return FALSE; 520848b8605Smrg } 521848b8605Smrg *index = (int) uindex; 522848b8605Smrg return TRUE; 523848b8605Smrg} 524848b8605Smrg 525848b8605Smrg/* Parse simple 1d register operand. 526848b8605Smrg * <register_dst> ::= <register_file_bracket_index> `]' 527848b8605Smrg */ 528848b8605Smrgstatic boolean 529848b8605Smrgparse_register_1d(struct translate_ctx *ctx, 530848b8605Smrg uint *file, 531848b8605Smrg int *index ) 532848b8605Smrg{ 533848b8605Smrg if (!parse_register_file_bracket_index( ctx, file, index )) 534848b8605Smrg return FALSE; 535848b8605Smrg eat_opt_white( &ctx->cur ); 536848b8605Smrg if (*ctx->cur != ']') { 537848b8605Smrg report_error( ctx, "Expected `]'" ); 538848b8605Smrg return FALSE; 539848b8605Smrg } 540848b8605Smrg ctx->cur++; 541848b8605Smrg return TRUE; 542848b8605Smrg} 543848b8605Smrg 544848b8605Smrgstruct parsed_bracket { 545848b8605Smrg int index; 546848b8605Smrg 547848b8605Smrg uint ind_file; 548848b8605Smrg int ind_index; 549848b8605Smrg uint ind_comp; 550848b8605Smrg uint ind_array; 551848b8605Smrg}; 552848b8605Smrg 553848b8605Smrg 554848b8605Smrgstatic boolean 555848b8605Smrgparse_register_bracket( 556848b8605Smrg struct translate_ctx *ctx, 557848b8605Smrg struct parsed_bracket *brackets) 558848b8605Smrg{ 559848b8605Smrg const char *cur; 560848b8605Smrg uint uindex; 561848b8605Smrg 562848b8605Smrg memset(brackets, 0, sizeof(struct parsed_bracket)); 563848b8605Smrg 564848b8605Smrg eat_opt_white( &ctx->cur ); 565848b8605Smrg 566848b8605Smrg cur = ctx->cur; 567848b8605Smrg if (parse_file( &cur, &brackets->ind_file )) { 568848b8605Smrg if (!parse_register_1d( ctx, &brackets->ind_file, 569848b8605Smrg &brackets->ind_index )) 570848b8605Smrg return FALSE; 571848b8605Smrg eat_opt_white( &ctx->cur ); 572848b8605Smrg 573848b8605Smrg if (*ctx->cur == '.') { 574848b8605Smrg ctx->cur++; 575848b8605Smrg eat_opt_white(&ctx->cur); 576848b8605Smrg 577848b8605Smrg switch (uprcase(*ctx->cur)) { 578848b8605Smrg case 'X': 579848b8605Smrg brackets->ind_comp = TGSI_SWIZZLE_X; 580848b8605Smrg break; 581848b8605Smrg case 'Y': 582848b8605Smrg brackets->ind_comp = TGSI_SWIZZLE_Y; 583848b8605Smrg break; 584848b8605Smrg case 'Z': 585848b8605Smrg brackets->ind_comp = TGSI_SWIZZLE_Z; 586848b8605Smrg break; 587848b8605Smrg case 'W': 588848b8605Smrg brackets->ind_comp = TGSI_SWIZZLE_W; 589848b8605Smrg break; 590848b8605Smrg default: 591848b8605Smrg report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'"); 592848b8605Smrg return FALSE; 593848b8605Smrg } 594848b8605Smrg ctx->cur++; 595848b8605Smrg eat_opt_white(&ctx->cur); 596848b8605Smrg } 597848b8605Smrg 598848b8605Smrg if (*ctx->cur == '+' || *ctx->cur == '-') 599848b8605Smrg parse_int( &ctx->cur, &brackets->index ); 600848b8605Smrg else 601848b8605Smrg brackets->index = 0; 602848b8605Smrg } 603848b8605Smrg else { 604848b8605Smrg if (!parse_uint( &ctx->cur, &uindex )) { 605848b8605Smrg report_error( ctx, "Expected literal unsigned integer" ); 606848b8605Smrg return FALSE; 607848b8605Smrg } 608848b8605Smrg brackets->index = (int) uindex; 609848b8605Smrg brackets->ind_file = TGSI_FILE_NULL; 610848b8605Smrg brackets->ind_index = 0; 611848b8605Smrg } 612848b8605Smrg eat_opt_white( &ctx->cur ); 613848b8605Smrg if (*ctx->cur != ']') { 614848b8605Smrg report_error( ctx, "Expected `]'" ); 615848b8605Smrg return FALSE; 616848b8605Smrg } 617848b8605Smrg ctx->cur++; 618848b8605Smrg if (*ctx->cur == '(') { 619848b8605Smrg ctx->cur++; 620848b8605Smrg eat_opt_white( &ctx->cur ); 621848b8605Smrg if (!parse_uint( &ctx->cur, &brackets->ind_array )) { 622848b8605Smrg report_error( ctx, "Expected literal unsigned integer" ); 623848b8605Smrg return FALSE; 624848b8605Smrg } 625848b8605Smrg eat_opt_white( &ctx->cur ); 626848b8605Smrg if (*ctx->cur != ')') { 627848b8605Smrg report_error( ctx, "Expected `)'" ); 628848b8605Smrg return FALSE; 629848b8605Smrg } 630848b8605Smrg ctx->cur++; 631848b8605Smrg } 632848b8605Smrg return TRUE; 633848b8605Smrg} 634848b8605Smrg 635848b8605Smrgstatic boolean 636848b8605Smrgparse_opt_register_src_bracket( 637848b8605Smrg struct translate_ctx *ctx, 638848b8605Smrg struct parsed_bracket *brackets, 639848b8605Smrg int *parsed_brackets) 640848b8605Smrg{ 641848b8605Smrg const char *cur = ctx->cur; 642848b8605Smrg 643848b8605Smrg *parsed_brackets = 0; 644848b8605Smrg 645848b8605Smrg eat_opt_white( &cur ); 646848b8605Smrg if (cur[0] == '[') { 647848b8605Smrg ++cur; 648848b8605Smrg ctx->cur = cur; 649848b8605Smrg 650848b8605Smrg if (!parse_register_bracket(ctx, brackets)) 651848b8605Smrg return FALSE; 652848b8605Smrg 653848b8605Smrg *parsed_brackets = 1; 654848b8605Smrg } 655848b8605Smrg 656848b8605Smrg return TRUE; 657848b8605Smrg} 658848b8605Smrg 659848b8605Smrg 660848b8605Smrg/* Parse source register operand. 661848b8605Smrg * <register_src> ::= <register_file_bracket_index> `]' | 662848b8605Smrg * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' | 663848b8605Smrg * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' | 664848b8605Smrg * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]' 665848b8605Smrg */ 666848b8605Smrgstatic boolean 667848b8605Smrgparse_register_src( 668848b8605Smrg struct translate_ctx *ctx, 669848b8605Smrg uint *file, 670848b8605Smrg struct parsed_bracket *brackets) 671848b8605Smrg{ 672848b8605Smrg brackets->ind_comp = TGSI_SWIZZLE_X; 673848b8605Smrg if (!parse_register_file_bracket( ctx, file )) 674848b8605Smrg return FALSE; 675848b8605Smrg if (!parse_register_bracket( ctx, brackets )) 676848b8605Smrg return FALSE; 677848b8605Smrg 678848b8605Smrg return TRUE; 679848b8605Smrg} 680848b8605Smrg 681848b8605Smrgstruct parsed_dcl_bracket { 682848b8605Smrg uint first; 683848b8605Smrg uint last; 684848b8605Smrg}; 685848b8605Smrg 686848b8605Smrgstatic boolean 687848b8605Smrgparse_register_dcl_bracket( 688848b8605Smrg struct translate_ctx *ctx, 689848b8605Smrg struct parsed_dcl_bracket *bracket) 690848b8605Smrg{ 691848b8605Smrg uint uindex; 692848b8605Smrg memset(bracket, 0, sizeof(struct parsed_dcl_bracket)); 693848b8605Smrg 694848b8605Smrg eat_opt_white( &ctx->cur ); 695848b8605Smrg 696848b8605Smrg if (!parse_uint( &ctx->cur, &uindex )) { 697848b8605Smrg /* it can be an empty bracket [] which means its range 698848b8605Smrg * is from 0 to some implied size */ 699848b8605Smrg if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) { 700848b8605Smrg bracket->first = 0; 701848b8605Smrg bracket->last = ctx->implied_array_size - 1; 702848b8605Smrg goto cleanup; 703848b8605Smrg } 704848b8605Smrg report_error( ctx, "Expected literal unsigned integer" ); 705848b8605Smrg return FALSE; 706848b8605Smrg } 707848b8605Smrg bracket->first = uindex; 708848b8605Smrg 709848b8605Smrg eat_opt_white( &ctx->cur ); 710848b8605Smrg 711848b8605Smrg if (ctx->cur[0] == '.' && ctx->cur[1] == '.') { 712848b8605Smrg uint uindex; 713848b8605Smrg 714848b8605Smrg ctx->cur += 2; 715848b8605Smrg eat_opt_white( &ctx->cur ); 716848b8605Smrg if (!parse_uint( &ctx->cur, &uindex )) { 717848b8605Smrg report_error( ctx, "Expected literal integer" ); 718848b8605Smrg return FALSE; 719848b8605Smrg } 720848b8605Smrg bracket->last = (int) uindex; 721848b8605Smrg eat_opt_white( &ctx->cur ); 722848b8605Smrg } 723848b8605Smrg else { 724848b8605Smrg bracket->last = bracket->first; 725848b8605Smrg } 726848b8605Smrg 727848b8605Smrgcleanup: 728848b8605Smrg if (*ctx->cur != ']') { 729848b8605Smrg report_error( ctx, "Expected `]' or `..'" ); 730848b8605Smrg return FALSE; 731848b8605Smrg } 732848b8605Smrg ctx->cur++; 733848b8605Smrg return TRUE; 734848b8605Smrg} 735848b8605Smrg 736848b8605Smrg/* Parse register declaration. 737848b8605Smrg * <register_dcl> ::= <register_file_bracket_index> `]' | 738848b8605Smrg * <register_file_bracket_index> `..' <index> `]' 739848b8605Smrg */ 740848b8605Smrgstatic boolean 741848b8605Smrgparse_register_dcl( 742848b8605Smrg struct translate_ctx *ctx, 743848b8605Smrg uint *file, 744848b8605Smrg struct parsed_dcl_bracket *brackets, 745848b8605Smrg int *num_brackets) 746848b8605Smrg{ 747848b8605Smrg const char *cur; 748848b8605Smrg 749848b8605Smrg *num_brackets = 0; 750848b8605Smrg 751848b8605Smrg if (!parse_register_file_bracket( ctx, file )) 752848b8605Smrg return FALSE; 753848b8605Smrg if (!parse_register_dcl_bracket( ctx, &brackets[0] )) 754848b8605Smrg return FALSE; 755848b8605Smrg 756848b8605Smrg *num_brackets = 1; 757848b8605Smrg 758848b8605Smrg cur = ctx->cur; 759848b8605Smrg eat_opt_white( &cur ); 760848b8605Smrg 761848b8605Smrg if (cur[0] == '[') { 762b8e80941Smrg bool is_in = *file == TGSI_FILE_INPUT; 763b8e80941Smrg bool is_out = *file == TGSI_FILE_OUTPUT; 764b8e80941Smrg 765848b8605Smrg ++cur; 766848b8605Smrg ctx->cur = cur; 767848b8605Smrg if (!parse_register_dcl_bracket( ctx, &brackets[1] )) 768848b8605Smrg return FALSE; 769848b8605Smrg /* for geometry shader we don't really care about 770848b8605Smrg * the first brackets it's always the size of the 771848b8605Smrg * input primitive. so we want to declare just 772848b8605Smrg * the index relevant to the semantics which is in 773848b8605Smrg * the second bracket */ 774b8e80941Smrg 775b8e80941Smrg /* tessellation has similar constraints to geometry shader */ 776b8e80941Smrg if ((ctx->processor == PIPE_SHADER_GEOMETRY && is_in) || 777b8e80941Smrg (ctx->processor == PIPE_SHADER_TESS_EVAL && is_in) || 778b8e80941Smrg (ctx->processor == PIPE_SHADER_TESS_CTRL && (is_in || is_out))) { 779848b8605Smrg brackets[0] = brackets[1]; 780848b8605Smrg *num_brackets = 1; 781848b8605Smrg } else { 782848b8605Smrg *num_brackets = 2; 783848b8605Smrg } 784848b8605Smrg } 785848b8605Smrg 786848b8605Smrg return TRUE; 787848b8605Smrg} 788848b8605Smrg 789848b8605Smrg 790848b8605Smrg/* Parse destination register operand.*/ 791848b8605Smrgstatic boolean 792848b8605Smrgparse_register_dst( 793848b8605Smrg struct translate_ctx *ctx, 794848b8605Smrg uint *file, 795848b8605Smrg struct parsed_bracket *brackets) 796848b8605Smrg{ 797848b8605Smrg brackets->ind_comp = TGSI_SWIZZLE_X; 798848b8605Smrg if (!parse_register_file_bracket( ctx, file )) 799848b8605Smrg return FALSE; 800848b8605Smrg if (!parse_register_bracket( ctx, brackets )) 801848b8605Smrg return FALSE; 802848b8605Smrg 803848b8605Smrg return TRUE; 804848b8605Smrg} 805848b8605Smrg 806848b8605Smrgstatic boolean 807848b8605Smrgparse_dst_operand( 808848b8605Smrg struct translate_ctx *ctx, 809848b8605Smrg struct tgsi_full_dst_register *dst ) 810848b8605Smrg{ 811848b8605Smrg uint file; 812848b8605Smrg uint writemask; 813848b8605Smrg const char *cur; 814848b8605Smrg struct parsed_bracket bracket[2]; 815848b8605Smrg int parsed_opt_brackets; 816848b8605Smrg 817848b8605Smrg if (!parse_register_dst( ctx, &file, &bracket[0] )) 818848b8605Smrg return FALSE; 819848b8605Smrg if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) 820848b8605Smrg return FALSE; 821848b8605Smrg 822848b8605Smrg cur = ctx->cur; 823848b8605Smrg eat_opt_white( &cur ); 824848b8605Smrg 825848b8605Smrg if (!parse_opt_writemask( ctx, &writemask )) 826848b8605Smrg return FALSE; 827848b8605Smrg 828848b8605Smrg dst->Register.File = file; 829848b8605Smrg if (parsed_opt_brackets) { 830848b8605Smrg dst->Register.Dimension = 1; 831848b8605Smrg dst->Dimension.Indirect = 0; 832848b8605Smrg dst->Dimension.Dimension = 0; 833848b8605Smrg dst->Dimension.Index = bracket[0].index; 834b8e80941Smrg 835b8e80941Smrg if (bracket[0].ind_file != TGSI_FILE_NULL) { 836b8e80941Smrg dst->Dimension.Indirect = 1; 837b8e80941Smrg dst->DimIndirect.File = bracket[0].ind_file; 838b8e80941Smrg dst->DimIndirect.Index = bracket[0].ind_index; 839b8e80941Smrg dst->DimIndirect.Swizzle = bracket[0].ind_comp; 840b8e80941Smrg dst->DimIndirect.ArrayID = bracket[0].ind_array; 841b8e80941Smrg } 842848b8605Smrg bracket[0] = bracket[1]; 843848b8605Smrg } 844848b8605Smrg dst->Register.Index = bracket[0].index; 845848b8605Smrg dst->Register.WriteMask = writemask; 846848b8605Smrg if (bracket[0].ind_file != TGSI_FILE_NULL) { 847848b8605Smrg dst->Register.Indirect = 1; 848848b8605Smrg dst->Indirect.File = bracket[0].ind_file; 849848b8605Smrg dst->Indirect.Index = bracket[0].ind_index; 850848b8605Smrg dst->Indirect.Swizzle = bracket[0].ind_comp; 851848b8605Smrg dst->Indirect.ArrayID = bracket[0].ind_array; 852848b8605Smrg } 853848b8605Smrg return TRUE; 854848b8605Smrg} 855848b8605Smrg 856848b8605Smrgstatic boolean 857848b8605Smrgparse_optional_swizzle( 858848b8605Smrg struct translate_ctx *ctx, 859848b8605Smrg uint *swizzle, 860848b8605Smrg boolean *parsed_swizzle, 861848b8605Smrg int components) 862848b8605Smrg{ 863848b8605Smrg const char *cur = ctx->cur; 864848b8605Smrg 865848b8605Smrg *parsed_swizzle = FALSE; 866848b8605Smrg 867848b8605Smrg eat_opt_white( &cur ); 868848b8605Smrg if (*cur == '.') { 869b8e80941Smrg int i; 870848b8605Smrg 871848b8605Smrg cur++; 872848b8605Smrg eat_opt_white( &cur ); 873848b8605Smrg for (i = 0; i < components; i++) { 874848b8605Smrg if (uprcase( *cur ) == 'X') 875848b8605Smrg swizzle[i] = TGSI_SWIZZLE_X; 876848b8605Smrg else if (uprcase( *cur ) == 'Y') 877848b8605Smrg swizzle[i] = TGSI_SWIZZLE_Y; 878848b8605Smrg else if (uprcase( *cur ) == 'Z') 879848b8605Smrg swizzle[i] = TGSI_SWIZZLE_Z; 880848b8605Smrg else if (uprcase( *cur ) == 'W') 881848b8605Smrg swizzle[i] = TGSI_SWIZZLE_W; 882848b8605Smrg else { 883848b8605Smrg report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" ); 884848b8605Smrg return FALSE; 885848b8605Smrg } 886848b8605Smrg cur++; 887848b8605Smrg } 888848b8605Smrg *parsed_swizzle = TRUE; 889848b8605Smrg ctx->cur = cur; 890848b8605Smrg } 891848b8605Smrg return TRUE; 892848b8605Smrg} 893848b8605Smrg 894848b8605Smrgstatic boolean 895848b8605Smrgparse_src_operand( 896848b8605Smrg struct translate_ctx *ctx, 897848b8605Smrg struct tgsi_full_src_register *src ) 898848b8605Smrg{ 899848b8605Smrg uint file; 900848b8605Smrg uint swizzle[4]; 901848b8605Smrg boolean parsed_swizzle; 902848b8605Smrg struct parsed_bracket bracket[2]; 903848b8605Smrg int parsed_opt_brackets; 904848b8605Smrg 905848b8605Smrg if (*ctx->cur == '-') { 906848b8605Smrg ctx->cur++; 907848b8605Smrg eat_opt_white( &ctx->cur ); 908848b8605Smrg src->Register.Negate = 1; 909848b8605Smrg } 910848b8605Smrg 911848b8605Smrg if (*ctx->cur == '|') { 912848b8605Smrg ctx->cur++; 913848b8605Smrg eat_opt_white( &ctx->cur ); 914848b8605Smrg src->Register.Absolute = 1; 915848b8605Smrg } 916848b8605Smrg 917848b8605Smrg if (!parse_register_src(ctx, &file, &bracket[0])) 918848b8605Smrg return FALSE; 919848b8605Smrg if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) 920848b8605Smrg return FALSE; 921848b8605Smrg 922848b8605Smrg src->Register.File = file; 923848b8605Smrg if (parsed_opt_brackets) { 924848b8605Smrg src->Register.Dimension = 1; 925848b8605Smrg src->Dimension.Indirect = 0; 926848b8605Smrg src->Dimension.Dimension = 0; 927848b8605Smrg src->Dimension.Index = bracket[0].index; 928848b8605Smrg if (bracket[0].ind_file != TGSI_FILE_NULL) { 929848b8605Smrg src->Dimension.Indirect = 1; 930848b8605Smrg src->DimIndirect.File = bracket[0].ind_file; 931848b8605Smrg src->DimIndirect.Index = bracket[0].ind_index; 932848b8605Smrg src->DimIndirect.Swizzle = bracket[0].ind_comp; 933848b8605Smrg src->DimIndirect.ArrayID = bracket[0].ind_array; 934848b8605Smrg } 935848b8605Smrg bracket[0] = bracket[1]; 936848b8605Smrg } 937848b8605Smrg src->Register.Index = bracket[0].index; 938848b8605Smrg if (bracket[0].ind_file != TGSI_FILE_NULL) { 939848b8605Smrg src->Register.Indirect = 1; 940848b8605Smrg src->Indirect.File = bracket[0].ind_file; 941848b8605Smrg src->Indirect.Index = bracket[0].ind_index; 942848b8605Smrg src->Indirect.Swizzle = bracket[0].ind_comp; 943848b8605Smrg src->Indirect.ArrayID = bracket[0].ind_array; 944848b8605Smrg } 945848b8605Smrg 946848b8605Smrg /* Parse optional swizzle. 947848b8605Smrg */ 948848b8605Smrg if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) { 949848b8605Smrg if (parsed_swizzle) { 950848b8605Smrg src->Register.SwizzleX = swizzle[0]; 951848b8605Smrg src->Register.SwizzleY = swizzle[1]; 952848b8605Smrg src->Register.SwizzleZ = swizzle[2]; 953848b8605Smrg src->Register.SwizzleW = swizzle[3]; 954848b8605Smrg } 955848b8605Smrg } 956848b8605Smrg 957848b8605Smrg if (src->Register.Absolute) { 958848b8605Smrg eat_opt_white( &ctx->cur ); 959848b8605Smrg if (*ctx->cur != '|') { 960848b8605Smrg report_error( ctx, "Expected `|'" ); 961848b8605Smrg return FALSE; 962848b8605Smrg } 963848b8605Smrg ctx->cur++; 964848b8605Smrg } 965848b8605Smrg 966848b8605Smrg 967848b8605Smrg return TRUE; 968848b8605Smrg} 969848b8605Smrg 970848b8605Smrgstatic boolean 971848b8605Smrgparse_texoffset_operand( 972848b8605Smrg struct translate_ctx *ctx, 973848b8605Smrg struct tgsi_texture_offset *src ) 974848b8605Smrg{ 975848b8605Smrg uint file; 976848b8605Smrg uint swizzle[3]; 977848b8605Smrg boolean parsed_swizzle; 978848b8605Smrg struct parsed_bracket bracket; 979848b8605Smrg 980848b8605Smrg if (!parse_register_src(ctx, &file, &bracket)) 981848b8605Smrg return FALSE; 982848b8605Smrg 983848b8605Smrg src->File = file; 984848b8605Smrg src->Index = bracket.index; 985848b8605Smrg 986848b8605Smrg /* Parse optional swizzle. 987848b8605Smrg */ 988848b8605Smrg if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) { 989848b8605Smrg if (parsed_swizzle) { 990848b8605Smrg src->SwizzleX = swizzle[0]; 991848b8605Smrg src->SwizzleY = swizzle[1]; 992848b8605Smrg src->SwizzleZ = swizzle[2]; 993848b8605Smrg } 994848b8605Smrg } 995848b8605Smrg 996848b8605Smrg return TRUE; 997848b8605Smrg} 998848b8605Smrg 999848b8605Smrgstatic boolean 1000848b8605Smrgmatch_inst(const char **pcur, 1001848b8605Smrg unsigned *saturate, 1002b8e80941Smrg unsigned *precise, 1003848b8605Smrg const struct tgsi_opcode_info *info) 1004848b8605Smrg{ 1005848b8605Smrg const char *cur = *pcur; 1006b8e80941Smrg const char *mnemonic = tgsi_get_opcode_name(info->opcode); 1007848b8605Smrg 1008848b8605Smrg /* simple case: the whole string matches the instruction name */ 1009b8e80941Smrg if (str_match_nocase_whole(&cur, mnemonic)) { 1010848b8605Smrg *pcur = cur; 1011b8e80941Smrg *saturate = 0; 1012b8e80941Smrg *precise = 0; 1013848b8605Smrg return TRUE; 1014848b8605Smrg } 1015848b8605Smrg 1016b8e80941Smrg if (str_match_no_case(&cur, mnemonic)) { 1017848b8605Smrg /* the instruction has a suffix, figure it out */ 1018b8e80941Smrg if (str_match_no_case(&cur, "_SAT")) { 1019848b8605Smrg *pcur = cur; 1020b8e80941Smrg *saturate = 1; 1021848b8605Smrg } 1022848b8605Smrg 1023b8e80941Smrg if (str_match_no_case(&cur, "_PRECISE")) { 1024848b8605Smrg *pcur = cur; 1025b8e80941Smrg *precise = 1; 1026848b8605Smrg } 1027b8e80941Smrg 1028b8e80941Smrg if (!is_digit_alpha_underscore(cur)) 1029b8e80941Smrg return TRUE; 1030848b8605Smrg } 1031848b8605Smrg 1032848b8605Smrg return FALSE; 1033848b8605Smrg} 1034848b8605Smrg 1035848b8605Smrgstatic boolean 1036848b8605Smrgparse_instruction( 1037848b8605Smrg struct translate_ctx *ctx, 1038848b8605Smrg boolean has_label ) 1039848b8605Smrg{ 1040b8e80941Smrg int i; 1041b8e80941Smrg uint saturate = 0; 1042b8e80941Smrg uint precise = 0; 1043848b8605Smrg const struct tgsi_opcode_info *info; 1044848b8605Smrg struct tgsi_full_instruction inst; 1045848b8605Smrg const char *cur; 1046848b8605Smrg uint advance; 1047848b8605Smrg 1048848b8605Smrg inst = tgsi_default_full_instruction(); 1049848b8605Smrg 1050848b8605Smrg /* Parse instruction name. 1051848b8605Smrg */ 1052848b8605Smrg eat_opt_white( &ctx->cur ); 1053848b8605Smrg for (i = 0; i < TGSI_OPCODE_LAST; i++) { 1054848b8605Smrg cur = ctx->cur; 1055848b8605Smrg 1056848b8605Smrg info = tgsi_get_opcode_info( i ); 1057b8e80941Smrg if (match_inst(&cur, &saturate, &precise, info)) { 1058848b8605Smrg if (info->num_dst + info->num_src + info->is_tex == 0) { 1059848b8605Smrg ctx->cur = cur; 1060848b8605Smrg break; 1061848b8605Smrg } 1062848b8605Smrg else if (*cur == '\0' || eat_white( &cur )) { 1063848b8605Smrg ctx->cur = cur; 1064848b8605Smrg break; 1065848b8605Smrg } 1066848b8605Smrg } 1067848b8605Smrg } 1068848b8605Smrg if (i == TGSI_OPCODE_LAST) { 1069848b8605Smrg if (has_label) 1070848b8605Smrg report_error( ctx, "Unknown opcode" ); 1071848b8605Smrg else 1072848b8605Smrg report_error( ctx, "Expected `DCL', `IMM' or a label" ); 1073848b8605Smrg return FALSE; 1074848b8605Smrg } 1075848b8605Smrg 1076848b8605Smrg inst.Instruction.Opcode = i; 1077848b8605Smrg inst.Instruction.Saturate = saturate; 1078b8e80941Smrg inst.Instruction.Precise = precise; 1079848b8605Smrg inst.Instruction.NumDstRegs = info->num_dst; 1080848b8605Smrg inst.Instruction.NumSrcRegs = info->num_src; 1081848b8605Smrg 1082848b8605Smrg if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { 1083848b8605Smrg /* 1084848b8605Smrg * These are not considered tex opcodes here (no additional 1085848b8605Smrg * target argument) however we're required to set the Texture 1086b8e80941Smrg * bit so we can set the number of tex offsets. 1087848b8605Smrg */ 1088848b8605Smrg inst.Instruction.Texture = 1; 1089848b8605Smrg inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; 1090848b8605Smrg } 1091848b8605Smrg 1092b8e80941Smrg if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || 1093b8e80941Smrg i == TGSI_OPCODE_RESQ) { 1094b8e80941Smrg inst.Instruction.Memory = 1; 1095b8e80941Smrg inst.Memory.Qualifier = 0; 1096b8e80941Smrg } 1097b8e80941Smrg 1098b8e80941Smrg assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS); 1099b8e80941Smrg assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS); 1100b8e80941Smrg 1101848b8605Smrg /* Parse instruction operands. 1102848b8605Smrg */ 1103848b8605Smrg for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { 1104848b8605Smrg if (i > 0) { 1105848b8605Smrg eat_opt_white( &ctx->cur ); 1106848b8605Smrg if (*ctx->cur != ',') { 1107848b8605Smrg report_error( ctx, "Expected `,'" ); 1108848b8605Smrg return FALSE; 1109848b8605Smrg } 1110848b8605Smrg ctx->cur++; 1111848b8605Smrg eat_opt_white( &ctx->cur ); 1112848b8605Smrg } 1113848b8605Smrg 1114848b8605Smrg if (i < info->num_dst) { 1115848b8605Smrg if (!parse_dst_operand( ctx, &inst.Dst[i] )) 1116848b8605Smrg return FALSE; 1117848b8605Smrg } 1118848b8605Smrg else if (i < info->num_dst + info->num_src) { 1119848b8605Smrg if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) 1120848b8605Smrg return FALSE; 1121848b8605Smrg } 1122848b8605Smrg else { 1123848b8605Smrg uint j; 1124848b8605Smrg 1125848b8605Smrg for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { 1126848b8605Smrg if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { 1127848b8605Smrg inst.Instruction.Texture = 1; 1128848b8605Smrg inst.Texture.Texture = j; 1129848b8605Smrg break; 1130848b8605Smrg } 1131848b8605Smrg } 1132848b8605Smrg if (j == TGSI_TEXTURE_COUNT) { 1133848b8605Smrg report_error( ctx, "Expected texture target" ); 1134848b8605Smrg return FALSE; 1135848b8605Smrg } 1136848b8605Smrg } 1137848b8605Smrg } 1138848b8605Smrg 1139848b8605Smrg cur = ctx->cur; 1140848b8605Smrg eat_opt_white( &cur ); 1141b8e80941Smrg for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) { 1142848b8605Smrg cur++; 1143848b8605Smrg eat_opt_white( &cur ); 1144848b8605Smrg ctx->cur = cur; 1145848b8605Smrg if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] )) 1146848b8605Smrg return FALSE; 1147848b8605Smrg cur = ctx->cur; 1148848b8605Smrg eat_opt_white( &cur ); 1149848b8605Smrg } 1150848b8605Smrg inst.Texture.NumOffsets = i; 1151848b8605Smrg 1152b8e80941Smrg cur = ctx->cur; 1153b8e80941Smrg eat_opt_white(&cur); 1154b8e80941Smrg 1155b8e80941Smrg for (; inst.Instruction.Memory && *cur == ','; 1156b8e80941Smrg ctx->cur = cur, eat_opt_white(&cur)) { 1157b8e80941Smrg int j; 1158b8e80941Smrg 1159b8e80941Smrg cur++; 1160b8e80941Smrg eat_opt_white(&cur); 1161b8e80941Smrg 1162b8e80941Smrg j = str_match_name_from_array(&cur, tgsi_memory_names, 1163b8e80941Smrg ARRAY_SIZE(tgsi_memory_names)); 1164b8e80941Smrg if (j >= 0) { 1165b8e80941Smrg inst.Memory.Qualifier |= 1U << j; 1166b8e80941Smrg continue; 1167b8e80941Smrg } 1168b8e80941Smrg 1169b8e80941Smrg j = str_match_name_from_array(&cur, tgsi_texture_names, 1170b8e80941Smrg ARRAY_SIZE(tgsi_texture_names)); 1171b8e80941Smrg if (j >= 0) { 1172b8e80941Smrg inst.Memory.Texture = j; 1173b8e80941Smrg continue; 1174b8e80941Smrg } 1175b8e80941Smrg 1176b8e80941Smrg j = str_match_format(&cur); 1177b8e80941Smrg if (j >= 0) { 1178b8e80941Smrg inst.Memory.Format = j; 1179b8e80941Smrg continue; 1180b8e80941Smrg } 1181b8e80941Smrg 1182b8e80941Smrg ctx->cur = cur; 1183b8e80941Smrg report_error(ctx, "Expected memory qualifier, texture target, or format\n"); 1184b8e80941Smrg return FALSE; 1185b8e80941Smrg } 1186b8e80941Smrg 1187848b8605Smrg cur = ctx->cur; 1188848b8605Smrg eat_opt_white( &cur ); 1189848b8605Smrg if (info->is_branch && *cur == ':') { 1190848b8605Smrg uint target; 1191848b8605Smrg 1192848b8605Smrg cur++; 1193848b8605Smrg eat_opt_white( &cur ); 1194848b8605Smrg if (!parse_uint( &cur, &target )) { 1195848b8605Smrg report_error( ctx, "Expected a label" ); 1196848b8605Smrg return FALSE; 1197848b8605Smrg } 1198848b8605Smrg inst.Instruction.Label = 1; 1199848b8605Smrg inst.Label.Label = target; 1200848b8605Smrg ctx->cur = cur; 1201848b8605Smrg } 1202848b8605Smrg 1203848b8605Smrg advance = tgsi_build_full_instruction( 1204848b8605Smrg &inst, 1205848b8605Smrg ctx->tokens_cur, 1206848b8605Smrg ctx->header, 1207848b8605Smrg (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1208848b8605Smrg if (advance == 0) 1209848b8605Smrg return FALSE; 1210848b8605Smrg ctx->tokens_cur += advance; 1211848b8605Smrg 1212848b8605Smrg return TRUE; 1213848b8605Smrg} 1214848b8605Smrg 1215848b8605Smrg/* parses a 4-touple of the form {x, y, z, w} 1216848b8605Smrg * where x, y, z, w are numbers */ 1217848b8605Smrgstatic boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type, 1218848b8605Smrg union tgsi_immediate_data *values) 1219848b8605Smrg{ 1220848b8605Smrg unsigned i; 1221848b8605Smrg int ret; 1222848b8605Smrg 1223848b8605Smrg eat_opt_white( &ctx->cur ); 1224848b8605Smrg if (*ctx->cur != '{') { 1225848b8605Smrg report_error( ctx, "Expected `{'" ); 1226848b8605Smrg return FALSE; 1227848b8605Smrg } 1228848b8605Smrg ctx->cur++; 1229848b8605Smrg for (i = 0; i < 4; i++) { 1230848b8605Smrg eat_opt_white( &ctx->cur ); 1231848b8605Smrg if (i > 0) { 1232848b8605Smrg if (*ctx->cur != ',') { 1233848b8605Smrg report_error( ctx, "Expected `,'" ); 1234848b8605Smrg return FALSE; 1235848b8605Smrg } 1236848b8605Smrg ctx->cur++; 1237848b8605Smrg eat_opt_white( &ctx->cur ); 1238848b8605Smrg } 1239848b8605Smrg 1240848b8605Smrg switch (type) { 1241b8e80941Smrg case TGSI_IMM_FLOAT64: 1242b8e80941Smrg ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1243b8e80941Smrg i++; 1244b8e80941Smrg break; 1245b8e80941Smrg case TGSI_IMM_INT64: 1246b8e80941Smrg ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1247b8e80941Smrg i++; 1248b8e80941Smrg break; 1249b8e80941Smrg case TGSI_IMM_UINT64: 1250b8e80941Smrg ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1251b8e80941Smrg i++; 1252b8e80941Smrg break; 1253848b8605Smrg case TGSI_IMM_FLOAT32: 1254848b8605Smrg ret = parse_float(&ctx->cur, &values[i].Float); 1255848b8605Smrg break; 1256848b8605Smrg case TGSI_IMM_UINT32: 1257848b8605Smrg ret = parse_uint(&ctx->cur, &values[i].Uint); 1258848b8605Smrg break; 1259848b8605Smrg case TGSI_IMM_INT32: 1260848b8605Smrg ret = parse_int(&ctx->cur, &values[i].Int); 1261848b8605Smrg break; 1262848b8605Smrg default: 1263848b8605Smrg assert(0); 1264848b8605Smrg ret = FALSE; 1265848b8605Smrg break; 1266848b8605Smrg } 1267848b8605Smrg 1268848b8605Smrg if (!ret) { 1269848b8605Smrg report_error( ctx, "Expected immediate constant" ); 1270848b8605Smrg return FALSE; 1271848b8605Smrg } 1272848b8605Smrg } 1273848b8605Smrg eat_opt_white( &ctx->cur ); 1274848b8605Smrg if (*ctx->cur != '}') { 1275848b8605Smrg report_error( ctx, "Expected `}'" ); 1276848b8605Smrg return FALSE; 1277848b8605Smrg } 1278848b8605Smrg ctx->cur++; 1279848b8605Smrg 1280848b8605Smrg return TRUE; 1281848b8605Smrg} 1282848b8605Smrg 1283848b8605Smrgstatic boolean parse_declaration( struct translate_ctx *ctx ) 1284848b8605Smrg{ 1285848b8605Smrg struct tgsi_full_declaration decl; 1286848b8605Smrg uint file; 1287848b8605Smrg struct parsed_dcl_bracket brackets[2]; 1288848b8605Smrg int num_brackets; 1289848b8605Smrg uint writemask; 1290848b8605Smrg const char *cur, *cur2; 1291848b8605Smrg uint advance; 1292848b8605Smrg boolean is_vs_input; 1293848b8605Smrg 1294848b8605Smrg if (!eat_white( &ctx->cur )) { 1295848b8605Smrg report_error( ctx, "Syntax error" ); 1296848b8605Smrg return FALSE; 1297848b8605Smrg } 1298848b8605Smrg if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) 1299848b8605Smrg return FALSE; 1300848b8605Smrg if (!parse_opt_writemask( ctx, &writemask )) 1301848b8605Smrg return FALSE; 1302848b8605Smrg 1303848b8605Smrg decl = tgsi_default_full_declaration(); 1304848b8605Smrg decl.Declaration.File = file; 1305848b8605Smrg decl.Declaration.UsageMask = writemask; 1306848b8605Smrg 1307848b8605Smrg if (num_brackets == 1) { 1308848b8605Smrg decl.Range.First = brackets[0].first; 1309848b8605Smrg decl.Range.Last = brackets[0].last; 1310848b8605Smrg } else { 1311848b8605Smrg decl.Range.First = brackets[1].first; 1312848b8605Smrg decl.Range.Last = brackets[1].last; 1313848b8605Smrg 1314848b8605Smrg decl.Declaration.Dimension = 1; 1315848b8605Smrg decl.Dim.Index2D = brackets[0].first; 1316848b8605Smrg } 1317848b8605Smrg 1318848b8605Smrg is_vs_input = (file == TGSI_FILE_INPUT && 1319b8e80941Smrg ctx->processor == PIPE_SHADER_VERTEX); 1320848b8605Smrg 1321848b8605Smrg cur = ctx->cur; 1322848b8605Smrg eat_opt_white( &cur ); 1323848b8605Smrg if (*cur == ',') { 1324848b8605Smrg cur2 = cur; 1325848b8605Smrg cur2++; 1326848b8605Smrg eat_opt_white( &cur2 ); 1327848b8605Smrg if (str_match_nocase_whole( &cur2, "ARRAY" )) { 1328848b8605Smrg int arrayid; 1329848b8605Smrg if (*cur2 != '(') { 1330848b8605Smrg report_error( ctx, "Expected `('" ); 1331848b8605Smrg return FALSE; 1332848b8605Smrg } 1333848b8605Smrg cur2++; 1334848b8605Smrg eat_opt_white( &cur2 ); 1335848b8605Smrg if (!parse_int( &cur2, &arrayid )) { 1336848b8605Smrg report_error( ctx, "Expected `,'" ); 1337848b8605Smrg return FALSE; 1338848b8605Smrg } 1339848b8605Smrg eat_opt_white( &cur2 ); 1340848b8605Smrg if (*cur2 != ')') { 1341848b8605Smrg report_error( ctx, "Expected `)'" ); 1342848b8605Smrg return FALSE; 1343848b8605Smrg } 1344848b8605Smrg cur2++; 1345848b8605Smrg decl.Declaration.Array = 1; 1346848b8605Smrg decl.Array.ArrayID = arrayid; 1347848b8605Smrg ctx->cur = cur = cur2; 1348848b8605Smrg } 1349848b8605Smrg } 1350848b8605Smrg 1351848b8605Smrg if (*cur == ',' && !is_vs_input) { 1352848b8605Smrg uint i, j; 1353848b8605Smrg 1354848b8605Smrg cur++; 1355848b8605Smrg eat_opt_white( &cur ); 1356b8e80941Smrg if (file == TGSI_FILE_IMAGE) { 1357848b8605Smrg for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { 1358848b8605Smrg if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { 1359b8e80941Smrg decl.Image.Resource = i; 1360848b8605Smrg break; 1361848b8605Smrg } 1362848b8605Smrg } 1363848b8605Smrg if (i == TGSI_TEXTURE_COUNT) { 1364848b8605Smrg report_error(ctx, "Expected texture target"); 1365848b8605Smrg return FALSE; 1366848b8605Smrg } 1367848b8605Smrg 1368848b8605Smrg cur2 = cur; 1369848b8605Smrg eat_opt_white(&cur2); 1370848b8605Smrg while (*cur2 == ',') { 1371848b8605Smrg cur2++; 1372848b8605Smrg eat_opt_white(&cur2); 1373848b8605Smrg if (str_match_nocase_whole(&cur2, "RAW")) { 1374b8e80941Smrg decl.Image.Raw = 1; 1375848b8605Smrg 1376848b8605Smrg } else if (str_match_nocase_whole(&cur2, "WR")) { 1377b8e80941Smrg decl.Image.Writable = 1; 1378848b8605Smrg 1379848b8605Smrg } else { 1380b8e80941Smrg int format = str_match_format(&cur2); 1381b8e80941Smrg if (format < 0) 1382b8e80941Smrg break; 1383b8e80941Smrg 1384b8e80941Smrg decl.Image.Format = format; 1385848b8605Smrg } 1386848b8605Smrg cur = cur2; 1387848b8605Smrg eat_opt_white(&cur2); 1388848b8605Smrg } 1389848b8605Smrg 1390848b8605Smrg ctx->cur = cur; 1391848b8605Smrg 1392848b8605Smrg } else if (file == TGSI_FILE_SAMPLER_VIEW) { 1393848b8605Smrg for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { 1394848b8605Smrg if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { 1395848b8605Smrg decl.SamplerView.Resource = i; 1396848b8605Smrg break; 1397848b8605Smrg } 1398848b8605Smrg } 1399848b8605Smrg if (i == TGSI_TEXTURE_COUNT) { 1400848b8605Smrg report_error(ctx, "Expected texture target"); 1401848b8605Smrg return FALSE; 1402848b8605Smrg } 1403848b8605Smrg eat_opt_white( &cur ); 1404848b8605Smrg if (*cur != ',') { 1405848b8605Smrg report_error( ctx, "Expected `,'" ); 1406848b8605Smrg return FALSE; 1407848b8605Smrg } 1408848b8605Smrg ++cur; 1409848b8605Smrg eat_opt_white( &cur ); 1410848b8605Smrg for (j = 0; j < 4; ++j) { 1411b8e80941Smrg for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) { 1412b8e80941Smrg if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) { 1413848b8605Smrg switch (j) { 1414848b8605Smrg case 0: 1415848b8605Smrg decl.SamplerView.ReturnTypeX = i; 1416848b8605Smrg break; 1417848b8605Smrg case 1: 1418848b8605Smrg decl.SamplerView.ReturnTypeY = i; 1419848b8605Smrg break; 1420848b8605Smrg case 2: 1421848b8605Smrg decl.SamplerView.ReturnTypeZ = i; 1422848b8605Smrg break; 1423848b8605Smrg case 3: 1424848b8605Smrg decl.SamplerView.ReturnTypeW = i; 1425848b8605Smrg break; 1426848b8605Smrg default: 1427848b8605Smrg assert(0); 1428848b8605Smrg } 1429848b8605Smrg break; 1430848b8605Smrg } 1431848b8605Smrg } 1432b8e80941Smrg if (i == TGSI_RETURN_TYPE_COUNT) { 1433848b8605Smrg if (j == 0 || j > 2) { 1434848b8605Smrg report_error(ctx, "Expected type name"); 1435848b8605Smrg return FALSE; 1436848b8605Smrg } 1437848b8605Smrg break; 1438848b8605Smrg } else { 1439848b8605Smrg cur2 = cur; 1440848b8605Smrg eat_opt_white( &cur2 ); 1441848b8605Smrg if (*cur2 == ',') { 1442848b8605Smrg cur2++; 1443848b8605Smrg eat_opt_white( &cur2 ); 1444848b8605Smrg cur = cur2; 1445848b8605Smrg continue; 1446848b8605Smrg } else 1447848b8605Smrg break; 1448848b8605Smrg } 1449848b8605Smrg } 1450848b8605Smrg if (j < 4) { 1451848b8605Smrg decl.SamplerView.ReturnTypeY = 1452848b8605Smrg decl.SamplerView.ReturnTypeZ = 1453848b8605Smrg decl.SamplerView.ReturnTypeW = 1454848b8605Smrg decl.SamplerView.ReturnTypeX; 1455848b8605Smrg } 1456848b8605Smrg ctx->cur = cur; 1457b8e80941Smrg } else if (file == TGSI_FILE_BUFFER) { 1458b8e80941Smrg if (str_match_nocase_whole(&cur, "ATOMIC")) { 1459b8e80941Smrg decl.Declaration.Atomic = 1; 1460b8e80941Smrg ctx->cur = cur; 1461b8e80941Smrg } 1462b8e80941Smrg } else if (file == TGSI_FILE_MEMORY) { 1463b8e80941Smrg if (str_match_nocase_whole(&cur, "GLOBAL")) { 1464b8e80941Smrg /* Note this is a no-op global is the default */ 1465b8e80941Smrg decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL; 1466b8e80941Smrg ctx->cur = cur; 1467b8e80941Smrg } else if (str_match_nocase_whole(&cur, "SHARED")) { 1468b8e80941Smrg decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED; 1469b8e80941Smrg ctx->cur = cur; 1470b8e80941Smrg } else if (str_match_nocase_whole(&cur, "PRIVATE")) { 1471b8e80941Smrg decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE; 1472b8e80941Smrg ctx->cur = cur; 1473b8e80941Smrg } else if (str_match_nocase_whole(&cur, "INPUT")) { 1474b8e80941Smrg decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT; 1475b8e80941Smrg ctx->cur = cur; 1476b8e80941Smrg } 1477848b8605Smrg } else { 1478848b8605Smrg if (str_match_nocase_whole(&cur, "LOCAL")) { 1479848b8605Smrg decl.Declaration.Local = 1; 1480848b8605Smrg ctx->cur = cur; 1481848b8605Smrg } 1482848b8605Smrg 1483848b8605Smrg cur = ctx->cur; 1484848b8605Smrg eat_opt_white( &cur ); 1485848b8605Smrg if (*cur == ',') { 1486848b8605Smrg cur++; 1487848b8605Smrg eat_opt_white( &cur ); 1488848b8605Smrg 1489848b8605Smrg for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { 1490848b8605Smrg if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) { 1491848b8605Smrg uint index; 1492848b8605Smrg 1493848b8605Smrg cur2 = cur; 1494848b8605Smrg eat_opt_white( &cur2 ); 1495848b8605Smrg if (*cur2 == '[') { 1496848b8605Smrg cur2++; 1497848b8605Smrg eat_opt_white( &cur2 ); 1498848b8605Smrg if (!parse_uint( &cur2, &index )) { 1499848b8605Smrg report_error( ctx, "Expected literal integer" ); 1500848b8605Smrg return FALSE; 1501848b8605Smrg } 1502848b8605Smrg eat_opt_white( &cur2 ); 1503848b8605Smrg if (*cur2 != ']') { 1504848b8605Smrg report_error( ctx, "Expected `]'" ); 1505848b8605Smrg return FALSE; 1506848b8605Smrg } 1507848b8605Smrg cur2++; 1508848b8605Smrg 1509848b8605Smrg decl.Semantic.Index = index; 1510848b8605Smrg 1511848b8605Smrg cur = cur2; 1512848b8605Smrg } 1513848b8605Smrg 1514848b8605Smrg decl.Declaration.Semantic = 1; 1515848b8605Smrg decl.Semantic.Name = i; 1516848b8605Smrg 1517848b8605Smrg ctx->cur = cur; 1518848b8605Smrg break; 1519848b8605Smrg } 1520848b8605Smrg } 1521848b8605Smrg } 1522848b8605Smrg } 1523848b8605Smrg } 1524848b8605Smrg 1525b8e80941Smrg cur = ctx->cur; 1526b8e80941Smrg eat_opt_white( &cur ); 1527b8e80941Smrg if (*cur == ',' && 1528b8e80941Smrg file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) { 1529b8e80941Smrg cur++; 1530b8e80941Smrg eat_opt_white(&cur); 1531b8e80941Smrg if (str_match_nocase_whole(&cur, "STREAM")) { 1532b8e80941Smrg uint stream[4]; 1533b8e80941Smrg 1534b8e80941Smrg eat_opt_white(&cur); 1535b8e80941Smrg if (*cur != '(') { 1536b8e80941Smrg report_error(ctx, "Expected '('"); 1537b8e80941Smrg return FALSE; 1538b8e80941Smrg } 1539b8e80941Smrg cur++; 1540b8e80941Smrg 1541b8e80941Smrg for (int i = 0; i < 4; ++i) { 1542b8e80941Smrg eat_opt_white(&cur); 1543b8e80941Smrg if (!parse_uint(&cur, &stream[i])) { 1544b8e80941Smrg report_error(ctx, "Expected literal integer"); 1545b8e80941Smrg return FALSE; 1546b8e80941Smrg } 1547b8e80941Smrg 1548b8e80941Smrg eat_opt_white(&cur); 1549b8e80941Smrg if (i < 3) { 1550b8e80941Smrg if (*cur != ',') { 1551b8e80941Smrg report_error(ctx, "Expected ','"); 1552b8e80941Smrg return FALSE; 1553b8e80941Smrg } 1554b8e80941Smrg cur++; 1555b8e80941Smrg } 1556b8e80941Smrg } 1557b8e80941Smrg 1558b8e80941Smrg if (*cur != ')') { 1559b8e80941Smrg report_error(ctx, "Expected ')'"); 1560b8e80941Smrg return FALSE; 1561b8e80941Smrg } 1562b8e80941Smrg cur++; 1563b8e80941Smrg 1564b8e80941Smrg decl.Semantic.StreamX = stream[0]; 1565b8e80941Smrg decl.Semantic.StreamY = stream[1]; 1566b8e80941Smrg decl.Semantic.StreamZ = stream[2]; 1567b8e80941Smrg decl.Semantic.StreamW = stream[3]; 1568b8e80941Smrg 1569b8e80941Smrg ctx->cur = cur; 1570b8e80941Smrg } 1571b8e80941Smrg } 1572b8e80941Smrg 1573848b8605Smrg cur = ctx->cur; 1574848b8605Smrg eat_opt_white( &cur ); 1575848b8605Smrg if (*cur == ',' && !is_vs_input) { 1576848b8605Smrg uint i; 1577848b8605Smrg 1578848b8605Smrg cur++; 1579848b8605Smrg eat_opt_white( &cur ); 1580848b8605Smrg for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { 1581848b8605Smrg if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) { 1582848b8605Smrg decl.Declaration.Interpolate = 1; 1583848b8605Smrg decl.Interp.Interpolate = i; 1584848b8605Smrg 1585848b8605Smrg ctx->cur = cur; 1586848b8605Smrg break; 1587848b8605Smrg } 1588848b8605Smrg } 1589848b8605Smrg } 1590848b8605Smrg 1591848b8605Smrg cur = ctx->cur; 1592848b8605Smrg eat_opt_white( &cur ); 1593848b8605Smrg if (*cur == ',' && !is_vs_input) { 1594848b8605Smrg uint i; 1595848b8605Smrg 1596848b8605Smrg cur++; 1597848b8605Smrg eat_opt_white( &cur ); 1598848b8605Smrg for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) { 1599848b8605Smrg if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) { 1600848b8605Smrg decl.Interp.Location = i; 1601848b8605Smrg 1602848b8605Smrg ctx->cur = cur; 1603848b8605Smrg break; 1604848b8605Smrg } 1605848b8605Smrg } 1606848b8605Smrg } 1607848b8605Smrg 1608b8e80941Smrg cur = ctx->cur; 1609b8e80941Smrg eat_opt_white( &cur ); 1610b8e80941Smrg if (*cur == ',' && !is_vs_input) { 1611b8e80941Smrg cur++; 1612b8e80941Smrg eat_opt_white( &cur ); 1613b8e80941Smrg if (str_match_nocase_whole( &cur, tgsi_invariant_name )) { 1614b8e80941Smrg decl.Declaration.Invariant = 1; 1615b8e80941Smrg ctx->cur = cur; 1616b8e80941Smrg } else { 1617b8e80941Smrg report_error( ctx, "Expected semantic, interpolate attribute, or invariant "); 1618b8e80941Smrg return FALSE; 1619b8e80941Smrg } 1620b8e80941Smrg } 1621b8e80941Smrg 1622848b8605Smrg advance = tgsi_build_full_declaration( 1623848b8605Smrg &decl, 1624848b8605Smrg ctx->tokens_cur, 1625848b8605Smrg ctx->header, 1626848b8605Smrg (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1627848b8605Smrg 1628848b8605Smrg if (advance == 0) 1629848b8605Smrg return FALSE; 1630848b8605Smrg ctx->tokens_cur += advance; 1631848b8605Smrg 1632848b8605Smrg return TRUE; 1633848b8605Smrg} 1634848b8605Smrg 1635848b8605Smrgstatic boolean parse_immediate( struct translate_ctx *ctx ) 1636848b8605Smrg{ 1637848b8605Smrg struct tgsi_full_immediate imm; 1638848b8605Smrg uint advance; 1639b8e80941Smrg uint type; 1640848b8605Smrg 1641848b8605Smrg if (*ctx->cur == '[') { 1642848b8605Smrg uint uindex; 1643848b8605Smrg 1644848b8605Smrg ++ctx->cur; 1645848b8605Smrg 1646848b8605Smrg eat_opt_white( &ctx->cur ); 1647848b8605Smrg if (!parse_uint( &ctx->cur, &uindex )) { 1648848b8605Smrg report_error( ctx, "Expected literal unsigned integer" ); 1649848b8605Smrg return FALSE; 1650848b8605Smrg } 1651848b8605Smrg 1652848b8605Smrg if (uindex != ctx->num_immediates) { 1653848b8605Smrg report_error( ctx, "Immediates must be sorted" ); 1654848b8605Smrg return FALSE; 1655848b8605Smrg } 1656848b8605Smrg 1657848b8605Smrg eat_opt_white( &ctx->cur ); 1658848b8605Smrg if (*ctx->cur != ']') { 1659848b8605Smrg report_error( ctx, "Expected `]'" ); 1660848b8605Smrg return FALSE; 1661848b8605Smrg } 1662848b8605Smrg 1663848b8605Smrg ctx->cur++; 1664848b8605Smrg } 1665848b8605Smrg 1666848b8605Smrg if (!eat_white( &ctx->cur )) { 1667848b8605Smrg report_error( ctx, "Syntax error" ); 1668848b8605Smrg return FALSE; 1669848b8605Smrg } 1670b8e80941Smrg for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) { 1671848b8605Smrg if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type])) 1672848b8605Smrg break; 1673848b8605Smrg } 1674b8e80941Smrg if (type == ARRAY_SIZE(tgsi_immediate_type_names)) { 1675848b8605Smrg report_error( ctx, "Expected immediate type" ); 1676848b8605Smrg return FALSE; 1677848b8605Smrg } 1678848b8605Smrg 1679848b8605Smrg imm = tgsi_default_full_immediate(); 1680848b8605Smrg imm.Immediate.NrTokens += 4; 1681848b8605Smrg imm.Immediate.DataType = type; 1682848b8605Smrg parse_immediate_data(ctx, type, imm.u); 1683848b8605Smrg 1684848b8605Smrg advance = tgsi_build_full_immediate( 1685848b8605Smrg &imm, 1686848b8605Smrg ctx->tokens_cur, 1687848b8605Smrg ctx->header, 1688848b8605Smrg (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1689848b8605Smrg if (advance == 0) 1690848b8605Smrg return FALSE; 1691848b8605Smrg ctx->tokens_cur += advance; 1692848b8605Smrg 1693848b8605Smrg ctx->num_immediates++; 1694848b8605Smrg 1695848b8605Smrg return TRUE; 1696848b8605Smrg} 1697848b8605Smrg 1698848b8605Smrgstatic boolean 1699848b8605Smrgparse_primitive( const char **pcur, uint *primitive ) 1700848b8605Smrg{ 1701848b8605Smrg uint i; 1702848b8605Smrg 1703848b8605Smrg for (i = 0; i < PIPE_PRIM_MAX; i++) { 1704848b8605Smrg const char *cur = *pcur; 1705848b8605Smrg 1706848b8605Smrg if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) { 1707848b8605Smrg *primitive = i; 1708848b8605Smrg *pcur = cur; 1709848b8605Smrg return TRUE; 1710848b8605Smrg } 1711848b8605Smrg } 1712848b8605Smrg return FALSE; 1713848b8605Smrg} 1714848b8605Smrg 1715848b8605Smrgstatic boolean 1716848b8605Smrgparse_fs_coord_origin( const char **pcur, uint *fs_coord_origin ) 1717848b8605Smrg{ 1718848b8605Smrg uint i; 1719848b8605Smrg 1720b8e80941Smrg for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) { 1721848b8605Smrg const char *cur = *pcur; 1722848b8605Smrg 1723848b8605Smrg if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) { 1724848b8605Smrg *fs_coord_origin = i; 1725848b8605Smrg *pcur = cur; 1726848b8605Smrg return TRUE; 1727848b8605Smrg } 1728848b8605Smrg } 1729848b8605Smrg return FALSE; 1730848b8605Smrg} 1731848b8605Smrg 1732848b8605Smrgstatic boolean 1733848b8605Smrgparse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center ) 1734848b8605Smrg{ 1735848b8605Smrg uint i; 1736848b8605Smrg 1737b8e80941Smrg for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) { 1738848b8605Smrg const char *cur = *pcur; 1739848b8605Smrg 1740848b8605Smrg if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) { 1741848b8605Smrg *fs_coord_pixel_center = i; 1742848b8605Smrg *pcur = cur; 1743848b8605Smrg return TRUE; 1744848b8605Smrg } 1745848b8605Smrg } 1746848b8605Smrg return FALSE; 1747848b8605Smrg} 1748848b8605Smrg 1749b8e80941Smrgstatic boolean 1750b8e80941Smrgparse_property_next_shader( const char **pcur, uint *next_shader ) 1751b8e80941Smrg{ 1752b8e80941Smrg uint i; 1753b8e80941Smrg 1754b8e80941Smrg for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) { 1755b8e80941Smrg const char *cur = *pcur; 1756b8e80941Smrg 1757b8e80941Smrg if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) { 1758b8e80941Smrg *next_shader = i; 1759b8e80941Smrg *pcur = cur; 1760b8e80941Smrg return TRUE; 1761b8e80941Smrg } 1762b8e80941Smrg } 1763b8e80941Smrg return FALSE; 1764b8e80941Smrg} 1765848b8605Smrg 1766848b8605Smrgstatic boolean parse_property( struct translate_ctx *ctx ) 1767848b8605Smrg{ 1768848b8605Smrg struct tgsi_full_property prop; 1769848b8605Smrg uint property_name; 1770848b8605Smrg uint values[8]; 1771848b8605Smrg uint advance; 1772848b8605Smrg char id[64]; 1773848b8605Smrg 1774848b8605Smrg if (!eat_white( &ctx->cur )) { 1775848b8605Smrg report_error( ctx, "Syntax error" ); 1776848b8605Smrg return FALSE; 1777848b8605Smrg } 1778b8e80941Smrg if (!parse_identifier( &ctx->cur, id, sizeof(id) )) { 1779848b8605Smrg report_error( ctx, "Syntax error" ); 1780848b8605Smrg return FALSE; 1781848b8605Smrg } 1782848b8605Smrg for (property_name = 0; property_name < TGSI_PROPERTY_COUNT; 1783848b8605Smrg ++property_name) { 1784848b8605Smrg if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) { 1785848b8605Smrg break; 1786848b8605Smrg } 1787848b8605Smrg } 1788848b8605Smrg if (property_name >= TGSI_PROPERTY_COUNT) { 1789848b8605Smrg debug_printf( "\nError: Unknown property : '%s'", id ); 1790848b8605Smrg return FALSE; 1791848b8605Smrg } 1792848b8605Smrg 1793848b8605Smrg eat_opt_white( &ctx->cur ); 1794848b8605Smrg switch(property_name) { 1795848b8605Smrg case TGSI_PROPERTY_GS_INPUT_PRIM: 1796848b8605Smrg case TGSI_PROPERTY_GS_OUTPUT_PRIM: 1797848b8605Smrg if (!parse_primitive(&ctx->cur, &values[0] )) { 1798848b8605Smrg report_error( ctx, "Unknown primitive name as property!" ); 1799848b8605Smrg return FALSE; 1800848b8605Smrg } 1801848b8605Smrg if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM && 1802b8e80941Smrg ctx->processor == PIPE_SHADER_GEOMETRY) { 1803848b8605Smrg ctx->implied_array_size = u_vertices_per_prim(values[0]); 1804848b8605Smrg } 1805848b8605Smrg break; 1806848b8605Smrg case TGSI_PROPERTY_FS_COORD_ORIGIN: 1807848b8605Smrg if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) { 1808848b8605Smrg report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" ); 1809848b8605Smrg return FALSE; 1810848b8605Smrg } 1811848b8605Smrg break; 1812848b8605Smrg case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: 1813848b8605Smrg if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) { 1814848b8605Smrg report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" ); 1815848b8605Smrg return FALSE; 1816848b8605Smrg } 1817848b8605Smrg break; 1818b8e80941Smrg case TGSI_PROPERTY_NEXT_SHADER: 1819b8e80941Smrg if (!parse_property_next_shader(&ctx->cur, &values[0] )) { 1820b8e80941Smrg report_error( ctx, "Unknown next shader property value." ); 1821b8e80941Smrg return FALSE; 1822b8e80941Smrg } 1823b8e80941Smrg break; 1824848b8605Smrg case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS: 1825848b8605Smrg default: 1826848b8605Smrg if (!parse_uint(&ctx->cur, &values[0] )) { 1827848b8605Smrg report_error( ctx, "Expected unsigned integer as property!" ); 1828848b8605Smrg return FALSE; 1829848b8605Smrg } 1830848b8605Smrg } 1831848b8605Smrg 1832848b8605Smrg prop = tgsi_default_full_property(); 1833848b8605Smrg prop.Property.PropertyName = property_name; 1834848b8605Smrg prop.Property.NrTokens += 1; 1835848b8605Smrg prop.u[0].Data = values[0]; 1836848b8605Smrg 1837848b8605Smrg advance = tgsi_build_full_property( 1838848b8605Smrg &prop, 1839848b8605Smrg ctx->tokens_cur, 1840848b8605Smrg ctx->header, 1841848b8605Smrg (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1842848b8605Smrg if (advance == 0) 1843848b8605Smrg return FALSE; 1844848b8605Smrg ctx->tokens_cur += advance; 1845848b8605Smrg 1846848b8605Smrg return TRUE; 1847848b8605Smrg} 1848848b8605Smrg 1849848b8605Smrg 1850848b8605Smrgstatic boolean translate( struct translate_ctx *ctx ) 1851848b8605Smrg{ 1852848b8605Smrg eat_opt_white( &ctx->cur ); 1853848b8605Smrg if (!parse_header( ctx )) 1854848b8605Smrg return FALSE; 1855848b8605Smrg 1856b8e80941Smrg if (ctx->processor == PIPE_SHADER_TESS_CTRL || 1857b8e80941Smrg ctx->processor == PIPE_SHADER_TESS_EVAL) 1858b8e80941Smrg ctx->implied_array_size = 32; 1859b8e80941Smrg 1860848b8605Smrg while (*ctx->cur != '\0') { 1861848b8605Smrg uint label_val = 0; 1862848b8605Smrg if (!eat_white( &ctx->cur )) { 1863848b8605Smrg report_error( ctx, "Syntax error" ); 1864848b8605Smrg return FALSE; 1865848b8605Smrg } 1866848b8605Smrg 1867848b8605Smrg if (*ctx->cur == '\0') 1868848b8605Smrg break; 1869848b8605Smrg if (parse_label( ctx, &label_val )) { 1870848b8605Smrg if (!parse_instruction( ctx, TRUE )) 1871848b8605Smrg return FALSE; 1872848b8605Smrg } 1873848b8605Smrg else if (str_match_nocase_whole( &ctx->cur, "DCL" )) { 1874848b8605Smrg if (!parse_declaration( ctx )) 1875848b8605Smrg return FALSE; 1876848b8605Smrg } 1877848b8605Smrg else if (str_match_nocase_whole( &ctx->cur, "IMM" )) { 1878848b8605Smrg if (!parse_immediate( ctx )) 1879848b8605Smrg return FALSE; 1880848b8605Smrg } 1881848b8605Smrg else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) { 1882848b8605Smrg if (!parse_property( ctx )) 1883848b8605Smrg return FALSE; 1884848b8605Smrg } 1885848b8605Smrg else if (!parse_instruction( ctx, FALSE )) { 1886848b8605Smrg return FALSE; 1887848b8605Smrg } 1888848b8605Smrg } 1889848b8605Smrg 1890848b8605Smrg return TRUE; 1891848b8605Smrg} 1892848b8605Smrg 1893848b8605Smrgboolean 1894848b8605Smrgtgsi_text_translate( 1895848b8605Smrg const char *text, 1896848b8605Smrg struct tgsi_token *tokens, 1897848b8605Smrg uint num_tokens ) 1898848b8605Smrg{ 1899848b8605Smrg struct translate_ctx ctx = {0}; 1900848b8605Smrg 1901848b8605Smrg ctx.text = text; 1902848b8605Smrg ctx.cur = text; 1903848b8605Smrg ctx.tokens = tokens; 1904848b8605Smrg ctx.tokens_cur = tokens; 1905848b8605Smrg ctx.tokens_end = tokens + num_tokens; 1906848b8605Smrg 1907848b8605Smrg if (!translate( &ctx )) 1908848b8605Smrg return FALSE; 1909848b8605Smrg 1910848b8605Smrg return tgsi_sanity_check( tokens ); 1911848b8605Smrg} 1912