1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "util/u_debug.h" 29bf215546Sopenharmony_ci#include "util/u_memory.h" 30bf215546Sopenharmony_ci#include "util/u_prim.h" 31bf215546Sopenharmony_ci#include "pipe/p_defines.h" 32bf215546Sopenharmony_ci#include "util/u_inlines.h" 33bf215546Sopenharmony_ci#include "tgsi_text.h" 34bf215546Sopenharmony_ci#include "tgsi_build.h" 35bf215546Sopenharmony_ci#include "tgsi_info.h" 36bf215546Sopenharmony_ci#include "tgsi_parse.h" 37bf215546Sopenharmony_ci#include "tgsi_sanity.h" 38bf215546Sopenharmony_ci#include "tgsi_strings.h" 39bf215546Sopenharmony_ci#include "tgsi_util.h" 40bf215546Sopenharmony_ci#include "tgsi_dump.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_cistatic boolean is_alpha_underscore( const char *cur ) 43bf215546Sopenharmony_ci{ 44bf215546Sopenharmony_ci return 45bf215546Sopenharmony_ci (*cur >= 'a' && *cur <= 'z') || 46bf215546Sopenharmony_ci (*cur >= 'A' && *cur <= 'Z') || 47bf215546Sopenharmony_ci *cur == '_'; 48bf215546Sopenharmony_ci} 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_cistatic boolean is_digit( const char *cur ) 51bf215546Sopenharmony_ci{ 52bf215546Sopenharmony_ci return *cur >= '0' && *cur <= '9'; 53bf215546Sopenharmony_ci} 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cistatic boolean is_digit_alpha_underscore( const char *cur ) 56bf215546Sopenharmony_ci{ 57bf215546Sopenharmony_ci return is_digit( cur ) || is_alpha_underscore( cur ); 58bf215546Sopenharmony_ci} 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_cistatic char uprcase( char c ) 61bf215546Sopenharmony_ci{ 62bf215546Sopenharmony_ci if (c >= 'a' && c <= 'z') 63bf215546Sopenharmony_ci return c + 'A' - 'a'; 64bf215546Sopenharmony_ci return c; 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci/* 68bf215546Sopenharmony_ci * Ignore case of str1 and assume str1 is already uppercase. 69bf215546Sopenharmony_ci * Return TRUE iff str1 and str2 are equal. 70bf215546Sopenharmony_ci */ 71bf215546Sopenharmony_cistatic int 72bf215546Sopenharmony_cistreq_nocase_uprcase(const char *str1, 73bf215546Sopenharmony_ci const char *str2) 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci while (*str1 && *str2) { 76bf215546Sopenharmony_ci if (*str1 != uprcase(*str2)) 77bf215546Sopenharmony_ci return FALSE; 78bf215546Sopenharmony_ci str1++; 79bf215546Sopenharmony_ci str2++; 80bf215546Sopenharmony_ci } 81bf215546Sopenharmony_ci return *str1 == 0 && *str2 == 0; 82bf215546Sopenharmony_ci} 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci/* Return TRUE if both strings match. 85bf215546Sopenharmony_ci * The second string is terminated by zero. 86bf215546Sopenharmony_ci * The pointer to the first string is moved at end of the read word 87bf215546Sopenharmony_ci * on success. 88bf215546Sopenharmony_ci */ 89bf215546Sopenharmony_cistatic boolean str_match_no_case( const char **pcur, const char *str ) 90bf215546Sopenharmony_ci{ 91bf215546Sopenharmony_ci const char *cur = *pcur; 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci while (*str != '\0' && *str == uprcase( *cur )) { 94bf215546Sopenharmony_ci str++; 95bf215546Sopenharmony_ci cur++; 96bf215546Sopenharmony_ci } 97bf215546Sopenharmony_ci if (*str == '\0') { 98bf215546Sopenharmony_ci *pcur = cur; 99bf215546Sopenharmony_ci return TRUE; 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci return FALSE; 102bf215546Sopenharmony_ci} 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci/* Return TRUE if both strings match. 105bf215546Sopenharmony_ci * The first string is be terminated by a non-digit non-letter non-underscore 106bf215546Sopenharmony_ci * character, the second string is terminated by zero. 107bf215546Sopenharmony_ci * The pointer to the first string is moved at end of the read word 108bf215546Sopenharmony_ci * on success. 109bf215546Sopenharmony_ci */ 110bf215546Sopenharmony_cistatic boolean str_match_nocase_whole( const char **pcur, const char *str ) 111bf215546Sopenharmony_ci{ 112bf215546Sopenharmony_ci const char *cur = *pcur; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci if (str_match_no_case(&cur, str) && 115bf215546Sopenharmony_ci !is_digit_alpha_underscore(cur)) { 116bf215546Sopenharmony_ci *pcur = cur; 117bf215546Sopenharmony_ci return TRUE; 118bf215546Sopenharmony_ci } 119bf215546Sopenharmony_ci return FALSE; 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci/* Return the array index that matches starting at *pcur, where the string at 123bf215546Sopenharmony_ci * *pcur is terminated by a non-digit non-letter non-underscore. 124bf215546Sopenharmony_ci * Returns -1 if no match is found. 125bf215546Sopenharmony_ci * 126bf215546Sopenharmony_ci * On success, the pointer to the first string is moved to the end of the read 127bf215546Sopenharmony_ci * word. 128bf215546Sopenharmony_ci */ 129bf215546Sopenharmony_cistatic int str_match_name_from_array(const char **pcur, 130bf215546Sopenharmony_ci const char * const *array, 131bf215546Sopenharmony_ci unsigned array_size) 132bf215546Sopenharmony_ci{ 133bf215546Sopenharmony_ci for (unsigned j = 0; j < array_size; ++j) { 134bf215546Sopenharmony_ci if (str_match_nocase_whole(pcur, array[j])) 135bf215546Sopenharmony_ci return j; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci return -1; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci/* Return the format corresponding to the name at *pcur. 141bf215546Sopenharmony_ci * Returns -1 if there is no format name. 142bf215546Sopenharmony_ci * 143bf215546Sopenharmony_ci * On success, the pointer to the string is moved to the end of the read format 144bf215546Sopenharmony_ci * name. 145bf215546Sopenharmony_ci */ 146bf215546Sopenharmony_cistatic int str_match_format(const char **pcur) 147bf215546Sopenharmony_ci{ 148bf215546Sopenharmony_ci for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) { 149bf215546Sopenharmony_ci const struct util_format_description *desc = 150bf215546Sopenharmony_ci util_format_description(i); 151bf215546Sopenharmony_ci if (str_match_nocase_whole(pcur, desc->name)) { 152bf215546Sopenharmony_ci return i; 153bf215546Sopenharmony_ci } 154bf215546Sopenharmony_ci } 155bf215546Sopenharmony_ci return -1; 156bf215546Sopenharmony_ci} 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci/* Eat zero or more whitespaces. 159bf215546Sopenharmony_ci */ 160bf215546Sopenharmony_cistatic void eat_opt_white( const char **pcur ) 161bf215546Sopenharmony_ci{ 162bf215546Sopenharmony_ci while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n') 163bf215546Sopenharmony_ci (*pcur)++; 164bf215546Sopenharmony_ci} 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci/* Eat one or more whitespaces. 167bf215546Sopenharmony_ci * Return TRUE if at least one whitespace eaten. 168bf215546Sopenharmony_ci */ 169bf215546Sopenharmony_cistatic boolean eat_white( const char **pcur ) 170bf215546Sopenharmony_ci{ 171bf215546Sopenharmony_ci const char *cur = *pcur; 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci eat_opt_white( pcur ); 174bf215546Sopenharmony_ci return *pcur > cur; 175bf215546Sopenharmony_ci} 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci/* Parse unsigned integer. 178bf215546Sopenharmony_ci * No checks for overflow. 179bf215546Sopenharmony_ci */ 180bf215546Sopenharmony_cistatic boolean parse_uint( const char **pcur, uint *val ) 181bf215546Sopenharmony_ci{ 182bf215546Sopenharmony_ci const char *cur = *pcur; 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci if (is_digit( cur )) { 185bf215546Sopenharmony_ci *val = *cur++ - '0'; 186bf215546Sopenharmony_ci while (is_digit( cur )) 187bf215546Sopenharmony_ci *val = *val * 10 + *cur++ - '0'; 188bf215546Sopenharmony_ci *pcur = cur; 189bf215546Sopenharmony_ci return TRUE; 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci return FALSE; 192bf215546Sopenharmony_ci} 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_cistatic boolean parse_int( const char **pcur, int *val ) 195bf215546Sopenharmony_ci{ 196bf215546Sopenharmony_ci const char *cur = *pcur; 197bf215546Sopenharmony_ci int sign = (*cur == '-' ? -1 : 1); 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci if (*cur == '+' || *cur == '-') 200bf215546Sopenharmony_ci cur++; 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci if (parse_uint(&cur, (uint *)val)) { 203bf215546Sopenharmony_ci *val *= sign; 204bf215546Sopenharmony_ci *pcur = cur; 205bf215546Sopenharmony_ci return TRUE; 206bf215546Sopenharmony_ci } 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci return FALSE; 209bf215546Sopenharmony_ci} 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_cistatic boolean parse_identifier( const char **pcur, char *ret, size_t len ) 212bf215546Sopenharmony_ci{ 213bf215546Sopenharmony_ci const char *cur = *pcur; 214bf215546Sopenharmony_ci size_t i = 0; 215bf215546Sopenharmony_ci if (is_alpha_underscore( cur )) { 216bf215546Sopenharmony_ci ret[i++] = *cur++; 217bf215546Sopenharmony_ci while (is_alpha_underscore( cur ) || is_digit( cur )) { 218bf215546Sopenharmony_ci if (i == len - 1) 219bf215546Sopenharmony_ci return FALSE; 220bf215546Sopenharmony_ci ret[i++] = *cur++; 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci ret[i++] = '\0'; 223bf215546Sopenharmony_ci *pcur = cur; 224bf215546Sopenharmony_ci return TRUE; 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci return FALSE; 227bf215546Sopenharmony_ci} 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci/* Parse floating point. 230bf215546Sopenharmony_ci */ 231bf215546Sopenharmony_cistatic boolean parse_float( const char **pcur, float *val ) 232bf215546Sopenharmony_ci{ 233bf215546Sopenharmony_ci const char *cur = *pcur; 234bf215546Sopenharmony_ci boolean integral_part = FALSE; 235bf215546Sopenharmony_ci boolean fractional_part = FALSE; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci if (*cur == '0' && *(cur + 1) == 'x') { 238bf215546Sopenharmony_ci union fi fi; 239bf215546Sopenharmony_ci fi.ui = strtoul(cur, NULL, 16); 240bf215546Sopenharmony_ci *val = fi.f; 241bf215546Sopenharmony_ci cur += 10; 242bf215546Sopenharmony_ci goto out; 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci *val = (float) atof( cur ); 246bf215546Sopenharmony_ci if (*cur == '-' || *cur == '+') 247bf215546Sopenharmony_ci cur++; 248bf215546Sopenharmony_ci if (is_digit( cur )) { 249bf215546Sopenharmony_ci cur++; 250bf215546Sopenharmony_ci integral_part = TRUE; 251bf215546Sopenharmony_ci while (is_digit( cur )) 252bf215546Sopenharmony_ci cur++; 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci if (*cur == '.') { 255bf215546Sopenharmony_ci cur++; 256bf215546Sopenharmony_ci if (is_digit( cur )) { 257bf215546Sopenharmony_ci cur++; 258bf215546Sopenharmony_ci fractional_part = TRUE; 259bf215546Sopenharmony_ci while (is_digit( cur )) 260bf215546Sopenharmony_ci cur++; 261bf215546Sopenharmony_ci } 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci if (!integral_part && !fractional_part) 264bf215546Sopenharmony_ci return FALSE; 265bf215546Sopenharmony_ci if (uprcase( *cur ) == 'E') { 266bf215546Sopenharmony_ci cur++; 267bf215546Sopenharmony_ci if (*cur == '-' || *cur == '+') 268bf215546Sopenharmony_ci cur++; 269bf215546Sopenharmony_ci if (is_digit( cur )) { 270bf215546Sopenharmony_ci cur++; 271bf215546Sopenharmony_ci while (is_digit( cur )) 272bf215546Sopenharmony_ci cur++; 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci else 275bf215546Sopenharmony_ci return FALSE; 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ciout: 279bf215546Sopenharmony_ci *pcur = cur; 280bf215546Sopenharmony_ci return TRUE; 281bf215546Sopenharmony_ci} 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_cistatic boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1) 284bf215546Sopenharmony_ci{ 285bf215546Sopenharmony_ci const char *cur = *pcur; 286bf215546Sopenharmony_ci union { 287bf215546Sopenharmony_ci double dval; 288bf215546Sopenharmony_ci uint32_t uval[2]; 289bf215546Sopenharmony_ci } v; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci v.dval = strtod(cur, (char**)pcur); 292bf215546Sopenharmony_ci if (*pcur == cur) 293bf215546Sopenharmony_ci return FALSE; 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci *val0 = v.uval[0]; 296bf215546Sopenharmony_ci *val1 = v.uval[1]; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci return TRUE; 299bf215546Sopenharmony_ci} 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_cistatic boolean parse_int64( const char **pcur, uint32_t *val0, uint32_t *val1) 302bf215546Sopenharmony_ci{ 303bf215546Sopenharmony_ci const char *cur = *pcur; 304bf215546Sopenharmony_ci union { 305bf215546Sopenharmony_ci int64_t i64val; 306bf215546Sopenharmony_ci uint32_t uval[2]; 307bf215546Sopenharmony_ci } v; 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci v.i64val = strtoll(cur, (char**)pcur, 0); 310bf215546Sopenharmony_ci if (*pcur == cur) 311bf215546Sopenharmony_ci return FALSE; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci *val0 = v.uval[0]; 314bf215546Sopenharmony_ci *val1 = v.uval[1]; 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci return TRUE; 317bf215546Sopenharmony_ci} 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_cistatic boolean parse_uint64( const char **pcur, uint32_t *val0, uint32_t *val1) 320bf215546Sopenharmony_ci{ 321bf215546Sopenharmony_ci const char *cur = *pcur; 322bf215546Sopenharmony_ci union { 323bf215546Sopenharmony_ci uint64_t u64val; 324bf215546Sopenharmony_ci uint32_t uval[2]; 325bf215546Sopenharmony_ci } v; 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci v.u64val = strtoull(cur, (char**)pcur, 0); 328bf215546Sopenharmony_ci if (*pcur == cur) 329bf215546Sopenharmony_ci return FALSE; 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci *val0 = v.uval[0]; 332bf215546Sopenharmony_ci *val1 = v.uval[1]; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci return TRUE; 335bf215546Sopenharmony_ci} 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_cistruct translate_ctx 338bf215546Sopenharmony_ci{ 339bf215546Sopenharmony_ci const char *text; 340bf215546Sopenharmony_ci const char *cur; 341bf215546Sopenharmony_ci struct tgsi_token *tokens; 342bf215546Sopenharmony_ci struct tgsi_token *tokens_cur; 343bf215546Sopenharmony_ci struct tgsi_token *tokens_end; 344bf215546Sopenharmony_ci struct tgsi_header *header; 345bf215546Sopenharmony_ci unsigned processor : 4; 346bf215546Sopenharmony_ci unsigned implied_array_size : 6; 347bf215546Sopenharmony_ci unsigned num_immediates; 348bf215546Sopenharmony_ci}; 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_cistatic void report_error( struct translate_ctx *ctx, const char *msg ) 351bf215546Sopenharmony_ci{ 352bf215546Sopenharmony_ci int line = 1; 353bf215546Sopenharmony_ci int column = 1; 354bf215546Sopenharmony_ci const char *itr = ctx->text; 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci while (itr != ctx->cur) { 357bf215546Sopenharmony_ci if (*itr == '\n') { 358bf215546Sopenharmony_ci column = 1; 359bf215546Sopenharmony_ci ++line; 360bf215546Sopenharmony_ci } 361bf215546Sopenharmony_ci ++column; 362bf215546Sopenharmony_ci ++itr; 363bf215546Sopenharmony_ci } 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column ); 366bf215546Sopenharmony_ci} 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci/* Parse shader header. 369bf215546Sopenharmony_ci * Return TRUE for one of the following headers. 370bf215546Sopenharmony_ci * FRAG 371bf215546Sopenharmony_ci * GEOM 372bf215546Sopenharmony_ci * VERT 373bf215546Sopenharmony_ci */ 374bf215546Sopenharmony_cistatic boolean parse_header( struct translate_ctx *ctx ) 375bf215546Sopenharmony_ci{ 376bf215546Sopenharmony_ci uint processor; 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci if (str_match_nocase_whole( &ctx->cur, "FRAG" )) 379bf215546Sopenharmony_ci processor = PIPE_SHADER_FRAGMENT; 380bf215546Sopenharmony_ci else if (str_match_nocase_whole( &ctx->cur, "VERT" )) 381bf215546Sopenharmony_ci processor = PIPE_SHADER_VERTEX; 382bf215546Sopenharmony_ci else if (str_match_nocase_whole( &ctx->cur, "GEOM" )) 383bf215546Sopenharmony_ci processor = PIPE_SHADER_GEOMETRY; 384bf215546Sopenharmony_ci else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" )) 385bf215546Sopenharmony_ci processor = PIPE_SHADER_TESS_CTRL; 386bf215546Sopenharmony_ci else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" )) 387bf215546Sopenharmony_ci processor = PIPE_SHADER_TESS_EVAL; 388bf215546Sopenharmony_ci else if (str_match_nocase_whole( &ctx->cur, "COMP" )) 389bf215546Sopenharmony_ci processor = PIPE_SHADER_COMPUTE; 390bf215546Sopenharmony_ci else { 391bf215546Sopenharmony_ci report_error( ctx, "Unknown header" ); 392bf215546Sopenharmony_ci return FALSE; 393bf215546Sopenharmony_ci } 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci if (ctx->tokens_cur >= ctx->tokens_end) 396bf215546Sopenharmony_ci return FALSE; 397bf215546Sopenharmony_ci ctx->header = (struct tgsi_header *) ctx->tokens_cur++; 398bf215546Sopenharmony_ci *ctx->header = tgsi_build_header(); 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci if (ctx->tokens_cur >= ctx->tokens_end) 401bf215546Sopenharmony_ci return FALSE; 402bf215546Sopenharmony_ci *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header ); 403bf215546Sopenharmony_ci ctx->processor = processor; 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ci return TRUE; 406bf215546Sopenharmony_ci} 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_cistatic boolean parse_label( struct translate_ctx *ctx, uint *val ) 409bf215546Sopenharmony_ci{ 410bf215546Sopenharmony_ci const char *cur = ctx->cur; 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci if (parse_uint( &cur, val )) { 413bf215546Sopenharmony_ci eat_opt_white( &cur ); 414bf215546Sopenharmony_ci if (*cur == ':') { 415bf215546Sopenharmony_ci cur++; 416bf215546Sopenharmony_ci ctx->cur = cur; 417bf215546Sopenharmony_ci return TRUE; 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci return FALSE; 421bf215546Sopenharmony_ci} 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_cistatic boolean 424bf215546Sopenharmony_ciparse_file( const char **pcur, uint *file ) 425bf215546Sopenharmony_ci{ 426bf215546Sopenharmony_ci uint i; 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci for (i = 0; i < TGSI_FILE_COUNT; i++) { 429bf215546Sopenharmony_ci const char *cur = *pcur; 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) { 432bf215546Sopenharmony_ci *pcur = cur; 433bf215546Sopenharmony_ci *file = i; 434bf215546Sopenharmony_ci return TRUE; 435bf215546Sopenharmony_ci } 436bf215546Sopenharmony_ci } 437bf215546Sopenharmony_ci return FALSE; 438bf215546Sopenharmony_ci} 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_cistatic boolean 441bf215546Sopenharmony_ciparse_opt_writemask( 442bf215546Sopenharmony_ci struct translate_ctx *ctx, 443bf215546Sopenharmony_ci uint *writemask ) 444bf215546Sopenharmony_ci{ 445bf215546Sopenharmony_ci const char *cur; 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci cur = ctx->cur; 448bf215546Sopenharmony_ci eat_opt_white( &cur ); 449bf215546Sopenharmony_ci if (*cur == '.') { 450bf215546Sopenharmony_ci cur++; 451bf215546Sopenharmony_ci *writemask = TGSI_WRITEMASK_NONE; 452bf215546Sopenharmony_ci eat_opt_white( &cur ); 453bf215546Sopenharmony_ci if (uprcase( *cur ) == 'X') { 454bf215546Sopenharmony_ci cur++; 455bf215546Sopenharmony_ci *writemask |= TGSI_WRITEMASK_X; 456bf215546Sopenharmony_ci } 457bf215546Sopenharmony_ci if (uprcase( *cur ) == 'Y') { 458bf215546Sopenharmony_ci cur++; 459bf215546Sopenharmony_ci *writemask |= TGSI_WRITEMASK_Y; 460bf215546Sopenharmony_ci } 461bf215546Sopenharmony_ci if (uprcase( *cur ) == 'Z') { 462bf215546Sopenharmony_ci cur++; 463bf215546Sopenharmony_ci *writemask |= TGSI_WRITEMASK_Z; 464bf215546Sopenharmony_ci } 465bf215546Sopenharmony_ci if (uprcase( *cur ) == 'W') { 466bf215546Sopenharmony_ci cur++; 467bf215546Sopenharmony_ci *writemask |= TGSI_WRITEMASK_W; 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci if (*writemask == TGSI_WRITEMASK_NONE) { 471bf215546Sopenharmony_ci report_error( ctx, "Writemask expected" ); 472bf215546Sopenharmony_ci return FALSE; 473bf215546Sopenharmony_ci } 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci ctx->cur = cur; 476bf215546Sopenharmony_ci } 477bf215546Sopenharmony_ci else { 478bf215546Sopenharmony_ci *writemask = TGSI_WRITEMASK_XYZW; 479bf215546Sopenharmony_ci } 480bf215546Sopenharmony_ci return TRUE; 481bf215546Sopenharmony_ci} 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci/* <register_file_bracket> ::= <file> `[' 485bf215546Sopenharmony_ci */ 486bf215546Sopenharmony_cistatic boolean 487bf215546Sopenharmony_ciparse_register_file_bracket( 488bf215546Sopenharmony_ci struct translate_ctx *ctx, 489bf215546Sopenharmony_ci uint *file ) 490bf215546Sopenharmony_ci{ 491bf215546Sopenharmony_ci if (!parse_file( &ctx->cur, file )) { 492bf215546Sopenharmony_ci report_error( ctx, "Unknown register file" ); 493bf215546Sopenharmony_ci return FALSE; 494bf215546Sopenharmony_ci } 495bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 496bf215546Sopenharmony_ci if (*ctx->cur != '[') { 497bf215546Sopenharmony_ci report_error( ctx, "Expected `['" ); 498bf215546Sopenharmony_ci return FALSE; 499bf215546Sopenharmony_ci } 500bf215546Sopenharmony_ci ctx->cur++; 501bf215546Sopenharmony_ci return TRUE; 502bf215546Sopenharmony_ci} 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci/* <register_file_bracket_index> ::= <register_file_bracket> <uint> 505bf215546Sopenharmony_ci */ 506bf215546Sopenharmony_cistatic boolean 507bf215546Sopenharmony_ciparse_register_file_bracket_index( 508bf215546Sopenharmony_ci struct translate_ctx *ctx, 509bf215546Sopenharmony_ci uint *file, 510bf215546Sopenharmony_ci int *index ) 511bf215546Sopenharmony_ci{ 512bf215546Sopenharmony_ci uint uindex; 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci if (!parse_register_file_bracket( ctx, file )) 515bf215546Sopenharmony_ci return FALSE; 516bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 517bf215546Sopenharmony_ci if (!parse_uint( &ctx->cur, &uindex )) { 518bf215546Sopenharmony_ci report_error( ctx, "Expected literal unsigned integer" ); 519bf215546Sopenharmony_ci return FALSE; 520bf215546Sopenharmony_ci } 521bf215546Sopenharmony_ci *index = (int) uindex; 522bf215546Sopenharmony_ci return TRUE; 523bf215546Sopenharmony_ci} 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci/* Parse simple 1d register operand. 526bf215546Sopenharmony_ci * <register_dst> ::= <register_file_bracket_index> `]' 527bf215546Sopenharmony_ci */ 528bf215546Sopenharmony_cistatic boolean 529bf215546Sopenharmony_ciparse_register_1d(struct translate_ctx *ctx, 530bf215546Sopenharmony_ci uint *file, 531bf215546Sopenharmony_ci int *index ) 532bf215546Sopenharmony_ci{ 533bf215546Sopenharmony_ci if (!parse_register_file_bracket_index( ctx, file, index )) 534bf215546Sopenharmony_ci return FALSE; 535bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 536bf215546Sopenharmony_ci if (*ctx->cur != ']') { 537bf215546Sopenharmony_ci report_error( ctx, "Expected `]'" ); 538bf215546Sopenharmony_ci return FALSE; 539bf215546Sopenharmony_ci } 540bf215546Sopenharmony_ci ctx->cur++; 541bf215546Sopenharmony_ci return TRUE; 542bf215546Sopenharmony_ci} 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_cistruct parsed_bracket { 545bf215546Sopenharmony_ci int index; 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci uint ind_file; 548bf215546Sopenharmony_ci int ind_index; 549bf215546Sopenharmony_ci uint ind_comp; 550bf215546Sopenharmony_ci uint ind_array; 551bf215546Sopenharmony_ci}; 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_cistatic boolean 555bf215546Sopenharmony_ciparse_register_bracket( 556bf215546Sopenharmony_ci struct translate_ctx *ctx, 557bf215546Sopenharmony_ci struct parsed_bracket *brackets) 558bf215546Sopenharmony_ci{ 559bf215546Sopenharmony_ci const char *cur; 560bf215546Sopenharmony_ci uint uindex; 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_ci memset(brackets, 0, sizeof(struct parsed_bracket)); 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci cur = ctx->cur; 567bf215546Sopenharmony_ci if (parse_file( &cur, &brackets->ind_file )) { 568bf215546Sopenharmony_ci if (!parse_register_1d( ctx, &brackets->ind_file, 569bf215546Sopenharmony_ci &brackets->ind_index )) 570bf215546Sopenharmony_ci return FALSE; 571bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 572bf215546Sopenharmony_ci 573bf215546Sopenharmony_ci if (*ctx->cur == '.') { 574bf215546Sopenharmony_ci ctx->cur++; 575bf215546Sopenharmony_ci eat_opt_white(&ctx->cur); 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci switch (uprcase(*ctx->cur)) { 578bf215546Sopenharmony_ci case 'X': 579bf215546Sopenharmony_ci brackets->ind_comp = TGSI_SWIZZLE_X; 580bf215546Sopenharmony_ci break; 581bf215546Sopenharmony_ci case 'Y': 582bf215546Sopenharmony_ci brackets->ind_comp = TGSI_SWIZZLE_Y; 583bf215546Sopenharmony_ci break; 584bf215546Sopenharmony_ci case 'Z': 585bf215546Sopenharmony_ci brackets->ind_comp = TGSI_SWIZZLE_Z; 586bf215546Sopenharmony_ci break; 587bf215546Sopenharmony_ci case 'W': 588bf215546Sopenharmony_ci brackets->ind_comp = TGSI_SWIZZLE_W; 589bf215546Sopenharmony_ci break; 590bf215546Sopenharmony_ci default: 591bf215546Sopenharmony_ci report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'"); 592bf215546Sopenharmony_ci return FALSE; 593bf215546Sopenharmony_ci } 594bf215546Sopenharmony_ci ctx->cur++; 595bf215546Sopenharmony_ci eat_opt_white(&ctx->cur); 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci if (*ctx->cur == '+' || *ctx->cur == '-') 599bf215546Sopenharmony_ci parse_int( &ctx->cur, &brackets->index ); 600bf215546Sopenharmony_ci else 601bf215546Sopenharmony_ci brackets->index = 0; 602bf215546Sopenharmony_ci } 603bf215546Sopenharmony_ci else { 604bf215546Sopenharmony_ci if (!parse_uint( &ctx->cur, &uindex )) { 605bf215546Sopenharmony_ci report_error( ctx, "Expected literal unsigned integer" ); 606bf215546Sopenharmony_ci return FALSE; 607bf215546Sopenharmony_ci } 608bf215546Sopenharmony_ci brackets->index = (int) uindex; 609bf215546Sopenharmony_ci brackets->ind_file = TGSI_FILE_NULL; 610bf215546Sopenharmony_ci brackets->ind_index = 0; 611bf215546Sopenharmony_ci } 612bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 613bf215546Sopenharmony_ci if (*ctx->cur != ']') { 614bf215546Sopenharmony_ci report_error( ctx, "Expected `]'" ); 615bf215546Sopenharmony_ci return FALSE; 616bf215546Sopenharmony_ci } 617bf215546Sopenharmony_ci ctx->cur++; 618bf215546Sopenharmony_ci if (*ctx->cur == '(') { 619bf215546Sopenharmony_ci ctx->cur++; 620bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 621bf215546Sopenharmony_ci if (!parse_uint( &ctx->cur, &brackets->ind_array )) { 622bf215546Sopenharmony_ci report_error( ctx, "Expected literal unsigned integer" ); 623bf215546Sopenharmony_ci return FALSE; 624bf215546Sopenharmony_ci } 625bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 626bf215546Sopenharmony_ci if (*ctx->cur != ')') { 627bf215546Sopenharmony_ci report_error( ctx, "Expected `)'" ); 628bf215546Sopenharmony_ci return FALSE; 629bf215546Sopenharmony_ci } 630bf215546Sopenharmony_ci ctx->cur++; 631bf215546Sopenharmony_ci } 632bf215546Sopenharmony_ci return TRUE; 633bf215546Sopenharmony_ci} 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_cistatic boolean 636bf215546Sopenharmony_ciparse_opt_register_src_bracket( 637bf215546Sopenharmony_ci struct translate_ctx *ctx, 638bf215546Sopenharmony_ci struct parsed_bracket *brackets, 639bf215546Sopenharmony_ci int *parsed_brackets) 640bf215546Sopenharmony_ci{ 641bf215546Sopenharmony_ci const char *cur = ctx->cur; 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci *parsed_brackets = 0; 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_ci eat_opt_white( &cur ); 646bf215546Sopenharmony_ci if (cur[0] == '[') { 647bf215546Sopenharmony_ci ++cur; 648bf215546Sopenharmony_ci ctx->cur = cur; 649bf215546Sopenharmony_ci 650bf215546Sopenharmony_ci if (!parse_register_bracket(ctx, brackets)) 651bf215546Sopenharmony_ci return FALSE; 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci *parsed_brackets = 1; 654bf215546Sopenharmony_ci } 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_ci return TRUE; 657bf215546Sopenharmony_ci} 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_ci/* Parse source register operand. 661bf215546Sopenharmony_ci * <register_src> ::= <register_file_bracket_index> `]' | 662bf215546Sopenharmony_ci * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' | 663bf215546Sopenharmony_ci * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' | 664bf215546Sopenharmony_ci * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]' 665bf215546Sopenharmony_ci */ 666bf215546Sopenharmony_cistatic boolean 667bf215546Sopenharmony_ciparse_register_src( 668bf215546Sopenharmony_ci struct translate_ctx *ctx, 669bf215546Sopenharmony_ci uint *file, 670bf215546Sopenharmony_ci struct parsed_bracket *brackets) 671bf215546Sopenharmony_ci{ 672bf215546Sopenharmony_ci brackets->ind_comp = TGSI_SWIZZLE_X; 673bf215546Sopenharmony_ci if (!parse_register_file_bracket( ctx, file )) 674bf215546Sopenharmony_ci return FALSE; 675bf215546Sopenharmony_ci if (!parse_register_bracket( ctx, brackets )) 676bf215546Sopenharmony_ci return FALSE; 677bf215546Sopenharmony_ci 678bf215546Sopenharmony_ci return TRUE; 679bf215546Sopenharmony_ci} 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_cistruct parsed_dcl_bracket { 682bf215546Sopenharmony_ci uint first; 683bf215546Sopenharmony_ci uint last; 684bf215546Sopenharmony_ci}; 685bf215546Sopenharmony_ci 686bf215546Sopenharmony_cistatic boolean 687bf215546Sopenharmony_ciparse_register_dcl_bracket( 688bf215546Sopenharmony_ci struct translate_ctx *ctx, 689bf215546Sopenharmony_ci struct parsed_dcl_bracket *bracket) 690bf215546Sopenharmony_ci{ 691bf215546Sopenharmony_ci uint uindex; 692bf215546Sopenharmony_ci memset(bracket, 0, sizeof(struct parsed_dcl_bracket)); 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci if (!parse_uint( &ctx->cur, &uindex )) { 697bf215546Sopenharmony_ci /* it can be an empty bracket [] which means its range 698bf215546Sopenharmony_ci * is from 0 to some implied size */ 699bf215546Sopenharmony_ci if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) { 700bf215546Sopenharmony_ci bracket->first = 0; 701bf215546Sopenharmony_ci bracket->last = ctx->implied_array_size - 1; 702bf215546Sopenharmony_ci goto cleanup; 703bf215546Sopenharmony_ci } 704bf215546Sopenharmony_ci report_error( ctx, "Expected literal unsigned integer" ); 705bf215546Sopenharmony_ci return FALSE; 706bf215546Sopenharmony_ci } 707bf215546Sopenharmony_ci bracket->first = uindex; 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci if (ctx->cur[0] == '.' && ctx->cur[1] == '.') { 712bf215546Sopenharmony_ci uint uindex; 713bf215546Sopenharmony_ci 714bf215546Sopenharmony_ci ctx->cur += 2; 715bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 716bf215546Sopenharmony_ci if (!parse_uint( &ctx->cur, &uindex )) { 717bf215546Sopenharmony_ci report_error( ctx, "Expected literal integer" ); 718bf215546Sopenharmony_ci return FALSE; 719bf215546Sopenharmony_ci } 720bf215546Sopenharmony_ci bracket->last = (int) uindex; 721bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 722bf215546Sopenharmony_ci } 723bf215546Sopenharmony_ci else { 724bf215546Sopenharmony_ci bracket->last = bracket->first; 725bf215546Sopenharmony_ci } 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_cicleanup: 728bf215546Sopenharmony_ci if (*ctx->cur != ']') { 729bf215546Sopenharmony_ci report_error( ctx, "Expected `]' or `..'" ); 730bf215546Sopenharmony_ci return FALSE; 731bf215546Sopenharmony_ci } 732bf215546Sopenharmony_ci ctx->cur++; 733bf215546Sopenharmony_ci return TRUE; 734bf215546Sopenharmony_ci} 735bf215546Sopenharmony_ci 736bf215546Sopenharmony_ci/* Parse register declaration. 737bf215546Sopenharmony_ci * <register_dcl> ::= <register_file_bracket_index> `]' | 738bf215546Sopenharmony_ci * <register_file_bracket_index> `..' <index> `]' 739bf215546Sopenharmony_ci */ 740bf215546Sopenharmony_cistatic boolean 741bf215546Sopenharmony_ciparse_register_dcl( 742bf215546Sopenharmony_ci struct translate_ctx *ctx, 743bf215546Sopenharmony_ci uint *file, 744bf215546Sopenharmony_ci struct parsed_dcl_bracket *brackets, 745bf215546Sopenharmony_ci int *num_brackets) 746bf215546Sopenharmony_ci{ 747bf215546Sopenharmony_ci const char *cur; 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci *num_brackets = 0; 750bf215546Sopenharmony_ci 751bf215546Sopenharmony_ci if (!parse_register_file_bracket( ctx, file )) 752bf215546Sopenharmony_ci return FALSE; 753bf215546Sopenharmony_ci if (!parse_register_dcl_bracket( ctx, &brackets[0] )) 754bf215546Sopenharmony_ci return FALSE; 755bf215546Sopenharmony_ci 756bf215546Sopenharmony_ci *num_brackets = 1; 757bf215546Sopenharmony_ci 758bf215546Sopenharmony_ci cur = ctx->cur; 759bf215546Sopenharmony_ci eat_opt_white( &cur ); 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci if (cur[0] == '[') { 762bf215546Sopenharmony_ci bool is_in = *file == TGSI_FILE_INPUT; 763bf215546Sopenharmony_ci bool is_out = *file == TGSI_FILE_OUTPUT; 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci ++cur; 766bf215546Sopenharmony_ci ctx->cur = cur; 767bf215546Sopenharmony_ci if (!parse_register_dcl_bracket( ctx, &brackets[1] )) 768bf215546Sopenharmony_ci return FALSE; 769bf215546Sopenharmony_ci /* for geometry shader we don't really care about 770bf215546Sopenharmony_ci * the first brackets it's always the size of the 771bf215546Sopenharmony_ci * input primitive. so we want to declare just 772bf215546Sopenharmony_ci * the index relevant to the semantics which is in 773bf215546Sopenharmony_ci * the second bracket */ 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci /* tessellation has similar constraints to geometry shader */ 776bf215546Sopenharmony_ci if ((ctx->processor == PIPE_SHADER_GEOMETRY && is_in) || 777bf215546Sopenharmony_ci (ctx->processor == PIPE_SHADER_TESS_EVAL && is_in) || 778bf215546Sopenharmony_ci (ctx->processor == PIPE_SHADER_TESS_CTRL && (is_in || is_out))) { 779bf215546Sopenharmony_ci brackets[0] = brackets[1]; 780bf215546Sopenharmony_ci *num_brackets = 1; 781bf215546Sopenharmony_ci } else { 782bf215546Sopenharmony_ci *num_brackets = 2; 783bf215546Sopenharmony_ci } 784bf215546Sopenharmony_ci } 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ci return TRUE; 787bf215546Sopenharmony_ci} 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_ci/* Parse destination register operand.*/ 791bf215546Sopenharmony_cistatic boolean 792bf215546Sopenharmony_ciparse_register_dst( 793bf215546Sopenharmony_ci struct translate_ctx *ctx, 794bf215546Sopenharmony_ci uint *file, 795bf215546Sopenharmony_ci struct parsed_bracket *brackets) 796bf215546Sopenharmony_ci{ 797bf215546Sopenharmony_ci brackets->ind_comp = TGSI_SWIZZLE_X; 798bf215546Sopenharmony_ci if (!parse_register_file_bracket( ctx, file )) 799bf215546Sopenharmony_ci return FALSE; 800bf215546Sopenharmony_ci if (!parse_register_bracket( ctx, brackets )) 801bf215546Sopenharmony_ci return FALSE; 802bf215546Sopenharmony_ci 803bf215546Sopenharmony_ci return TRUE; 804bf215546Sopenharmony_ci} 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_cistatic boolean 807bf215546Sopenharmony_ciparse_dst_operand( 808bf215546Sopenharmony_ci struct translate_ctx *ctx, 809bf215546Sopenharmony_ci struct tgsi_full_dst_register *dst ) 810bf215546Sopenharmony_ci{ 811bf215546Sopenharmony_ci uint file; 812bf215546Sopenharmony_ci uint writemask; 813bf215546Sopenharmony_ci const char *cur; 814bf215546Sopenharmony_ci struct parsed_bracket bracket[2]; 815bf215546Sopenharmony_ci int parsed_opt_brackets; 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci if (!parse_register_dst( ctx, &file, &bracket[0] )) 818bf215546Sopenharmony_ci return FALSE; 819bf215546Sopenharmony_ci if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) 820bf215546Sopenharmony_ci return FALSE; 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci cur = ctx->cur; 823bf215546Sopenharmony_ci eat_opt_white( &cur ); 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci if (!parse_opt_writemask( ctx, &writemask )) 826bf215546Sopenharmony_ci return FALSE; 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci dst->Register.File = file; 829bf215546Sopenharmony_ci if (parsed_opt_brackets) { 830bf215546Sopenharmony_ci dst->Register.Dimension = 1; 831bf215546Sopenharmony_ci dst->Dimension.Indirect = 0; 832bf215546Sopenharmony_ci dst->Dimension.Dimension = 0; 833bf215546Sopenharmony_ci dst->Dimension.Index = bracket[0].index; 834bf215546Sopenharmony_ci 835bf215546Sopenharmony_ci if (bracket[0].ind_file != TGSI_FILE_NULL) { 836bf215546Sopenharmony_ci dst->Dimension.Indirect = 1; 837bf215546Sopenharmony_ci dst->DimIndirect.File = bracket[0].ind_file; 838bf215546Sopenharmony_ci dst->DimIndirect.Index = bracket[0].ind_index; 839bf215546Sopenharmony_ci dst->DimIndirect.Swizzle = bracket[0].ind_comp; 840bf215546Sopenharmony_ci dst->DimIndirect.ArrayID = bracket[0].ind_array; 841bf215546Sopenharmony_ci } 842bf215546Sopenharmony_ci bracket[0] = bracket[1]; 843bf215546Sopenharmony_ci } 844bf215546Sopenharmony_ci dst->Register.Index = bracket[0].index; 845bf215546Sopenharmony_ci dst->Register.WriteMask = writemask; 846bf215546Sopenharmony_ci if (bracket[0].ind_file != TGSI_FILE_NULL) { 847bf215546Sopenharmony_ci dst->Register.Indirect = 1; 848bf215546Sopenharmony_ci dst->Indirect.File = bracket[0].ind_file; 849bf215546Sopenharmony_ci dst->Indirect.Index = bracket[0].ind_index; 850bf215546Sopenharmony_ci dst->Indirect.Swizzle = bracket[0].ind_comp; 851bf215546Sopenharmony_ci dst->Indirect.ArrayID = bracket[0].ind_array; 852bf215546Sopenharmony_ci } 853bf215546Sopenharmony_ci return TRUE; 854bf215546Sopenharmony_ci} 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_cistatic boolean 857bf215546Sopenharmony_ciparse_optional_swizzle( 858bf215546Sopenharmony_ci struct translate_ctx *ctx, 859bf215546Sopenharmony_ci uint *swizzle, 860bf215546Sopenharmony_ci boolean *parsed_swizzle, 861bf215546Sopenharmony_ci int components) 862bf215546Sopenharmony_ci{ 863bf215546Sopenharmony_ci const char *cur = ctx->cur; 864bf215546Sopenharmony_ci 865bf215546Sopenharmony_ci *parsed_swizzle = FALSE; 866bf215546Sopenharmony_ci 867bf215546Sopenharmony_ci eat_opt_white( &cur ); 868bf215546Sopenharmony_ci if (*cur == '.') { 869bf215546Sopenharmony_ci int i; 870bf215546Sopenharmony_ci 871bf215546Sopenharmony_ci cur++; 872bf215546Sopenharmony_ci eat_opt_white( &cur ); 873bf215546Sopenharmony_ci for (i = 0; i < components; i++) { 874bf215546Sopenharmony_ci if (uprcase( *cur ) == 'X') 875bf215546Sopenharmony_ci swizzle[i] = TGSI_SWIZZLE_X; 876bf215546Sopenharmony_ci else if (uprcase( *cur ) == 'Y') 877bf215546Sopenharmony_ci swizzle[i] = TGSI_SWIZZLE_Y; 878bf215546Sopenharmony_ci else if (uprcase( *cur ) == 'Z') 879bf215546Sopenharmony_ci swizzle[i] = TGSI_SWIZZLE_Z; 880bf215546Sopenharmony_ci else if (uprcase( *cur ) == 'W') 881bf215546Sopenharmony_ci swizzle[i] = TGSI_SWIZZLE_W; 882bf215546Sopenharmony_ci else { 883bf215546Sopenharmony_ci report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" ); 884bf215546Sopenharmony_ci return FALSE; 885bf215546Sopenharmony_ci } 886bf215546Sopenharmony_ci cur++; 887bf215546Sopenharmony_ci } 888bf215546Sopenharmony_ci *parsed_swizzle = TRUE; 889bf215546Sopenharmony_ci ctx->cur = cur; 890bf215546Sopenharmony_ci } 891bf215546Sopenharmony_ci return TRUE; 892bf215546Sopenharmony_ci} 893bf215546Sopenharmony_ci 894bf215546Sopenharmony_cistatic boolean 895bf215546Sopenharmony_ciparse_src_operand( 896bf215546Sopenharmony_ci struct translate_ctx *ctx, 897bf215546Sopenharmony_ci struct tgsi_full_src_register *src ) 898bf215546Sopenharmony_ci{ 899bf215546Sopenharmony_ci uint file; 900bf215546Sopenharmony_ci uint swizzle[4]; 901bf215546Sopenharmony_ci boolean parsed_swizzle; 902bf215546Sopenharmony_ci struct parsed_bracket bracket[2]; 903bf215546Sopenharmony_ci int parsed_opt_brackets; 904bf215546Sopenharmony_ci 905bf215546Sopenharmony_ci if (*ctx->cur == '-') { 906bf215546Sopenharmony_ci ctx->cur++; 907bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 908bf215546Sopenharmony_ci src->Register.Negate = 1; 909bf215546Sopenharmony_ci } 910bf215546Sopenharmony_ci 911bf215546Sopenharmony_ci if (*ctx->cur == '|') { 912bf215546Sopenharmony_ci ctx->cur++; 913bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 914bf215546Sopenharmony_ci src->Register.Absolute = 1; 915bf215546Sopenharmony_ci } 916bf215546Sopenharmony_ci 917bf215546Sopenharmony_ci if (!parse_register_src(ctx, &file, &bracket[0])) 918bf215546Sopenharmony_ci return FALSE; 919bf215546Sopenharmony_ci if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) 920bf215546Sopenharmony_ci return FALSE; 921bf215546Sopenharmony_ci 922bf215546Sopenharmony_ci src->Register.File = file; 923bf215546Sopenharmony_ci if (parsed_opt_brackets) { 924bf215546Sopenharmony_ci src->Register.Dimension = 1; 925bf215546Sopenharmony_ci src->Dimension.Indirect = 0; 926bf215546Sopenharmony_ci src->Dimension.Dimension = 0; 927bf215546Sopenharmony_ci src->Dimension.Index = bracket[0].index; 928bf215546Sopenharmony_ci if (bracket[0].ind_file != TGSI_FILE_NULL) { 929bf215546Sopenharmony_ci src->Dimension.Indirect = 1; 930bf215546Sopenharmony_ci src->DimIndirect.File = bracket[0].ind_file; 931bf215546Sopenharmony_ci src->DimIndirect.Index = bracket[0].ind_index; 932bf215546Sopenharmony_ci src->DimIndirect.Swizzle = bracket[0].ind_comp; 933bf215546Sopenharmony_ci src->DimIndirect.ArrayID = bracket[0].ind_array; 934bf215546Sopenharmony_ci } 935bf215546Sopenharmony_ci bracket[0] = bracket[1]; 936bf215546Sopenharmony_ci } 937bf215546Sopenharmony_ci src->Register.Index = bracket[0].index; 938bf215546Sopenharmony_ci if (bracket[0].ind_file != TGSI_FILE_NULL) { 939bf215546Sopenharmony_ci src->Register.Indirect = 1; 940bf215546Sopenharmony_ci src->Indirect.File = bracket[0].ind_file; 941bf215546Sopenharmony_ci src->Indirect.Index = bracket[0].ind_index; 942bf215546Sopenharmony_ci src->Indirect.Swizzle = bracket[0].ind_comp; 943bf215546Sopenharmony_ci src->Indirect.ArrayID = bracket[0].ind_array; 944bf215546Sopenharmony_ci } 945bf215546Sopenharmony_ci 946bf215546Sopenharmony_ci /* Parse optional swizzle. 947bf215546Sopenharmony_ci */ 948bf215546Sopenharmony_ci if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) { 949bf215546Sopenharmony_ci if (parsed_swizzle) { 950bf215546Sopenharmony_ci src->Register.SwizzleX = swizzle[0]; 951bf215546Sopenharmony_ci src->Register.SwizzleY = swizzle[1]; 952bf215546Sopenharmony_ci src->Register.SwizzleZ = swizzle[2]; 953bf215546Sopenharmony_ci src->Register.SwizzleW = swizzle[3]; 954bf215546Sopenharmony_ci } 955bf215546Sopenharmony_ci } 956bf215546Sopenharmony_ci 957bf215546Sopenharmony_ci if (src->Register.Absolute) { 958bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 959bf215546Sopenharmony_ci if (*ctx->cur != '|') { 960bf215546Sopenharmony_ci report_error( ctx, "Expected `|'" ); 961bf215546Sopenharmony_ci return FALSE; 962bf215546Sopenharmony_ci } 963bf215546Sopenharmony_ci ctx->cur++; 964bf215546Sopenharmony_ci } 965bf215546Sopenharmony_ci 966bf215546Sopenharmony_ci 967bf215546Sopenharmony_ci return TRUE; 968bf215546Sopenharmony_ci} 969bf215546Sopenharmony_ci 970bf215546Sopenharmony_cistatic boolean 971bf215546Sopenharmony_ciparse_texoffset_operand( 972bf215546Sopenharmony_ci struct translate_ctx *ctx, 973bf215546Sopenharmony_ci struct tgsi_texture_offset *src ) 974bf215546Sopenharmony_ci{ 975bf215546Sopenharmony_ci uint file; 976bf215546Sopenharmony_ci uint swizzle[3]; 977bf215546Sopenharmony_ci boolean parsed_swizzle; 978bf215546Sopenharmony_ci struct parsed_bracket bracket; 979bf215546Sopenharmony_ci 980bf215546Sopenharmony_ci if (!parse_register_src(ctx, &file, &bracket)) 981bf215546Sopenharmony_ci return FALSE; 982bf215546Sopenharmony_ci 983bf215546Sopenharmony_ci src->File = file; 984bf215546Sopenharmony_ci src->Index = bracket.index; 985bf215546Sopenharmony_ci 986bf215546Sopenharmony_ci /* Parse optional swizzle. 987bf215546Sopenharmony_ci */ 988bf215546Sopenharmony_ci if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) { 989bf215546Sopenharmony_ci if (parsed_swizzle) { 990bf215546Sopenharmony_ci src->SwizzleX = swizzle[0]; 991bf215546Sopenharmony_ci src->SwizzleY = swizzle[1]; 992bf215546Sopenharmony_ci src->SwizzleZ = swizzle[2]; 993bf215546Sopenharmony_ci } 994bf215546Sopenharmony_ci } 995bf215546Sopenharmony_ci 996bf215546Sopenharmony_ci return TRUE; 997bf215546Sopenharmony_ci} 998bf215546Sopenharmony_ci 999bf215546Sopenharmony_cistatic boolean 1000bf215546Sopenharmony_cimatch_inst(const char **pcur, 1001bf215546Sopenharmony_ci unsigned *saturate, 1002bf215546Sopenharmony_ci unsigned *precise, 1003bf215546Sopenharmony_ci const struct tgsi_opcode_info *info) 1004bf215546Sopenharmony_ci{ 1005bf215546Sopenharmony_ci const char *cur = *pcur; 1006bf215546Sopenharmony_ci const char *mnemonic = tgsi_get_opcode_name(info->opcode); 1007bf215546Sopenharmony_ci 1008bf215546Sopenharmony_ci /* simple case: the whole string matches the instruction name */ 1009bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur, mnemonic)) { 1010bf215546Sopenharmony_ci *pcur = cur; 1011bf215546Sopenharmony_ci *saturate = 0; 1012bf215546Sopenharmony_ci *precise = 0; 1013bf215546Sopenharmony_ci return TRUE; 1014bf215546Sopenharmony_ci } 1015bf215546Sopenharmony_ci 1016bf215546Sopenharmony_ci if (str_match_no_case(&cur, mnemonic)) { 1017bf215546Sopenharmony_ci /* the instruction has a suffix, figure it out */ 1018bf215546Sopenharmony_ci if (str_match_no_case(&cur, "_SAT")) { 1019bf215546Sopenharmony_ci *pcur = cur; 1020bf215546Sopenharmony_ci *saturate = 1; 1021bf215546Sopenharmony_ci } 1022bf215546Sopenharmony_ci 1023bf215546Sopenharmony_ci if (str_match_no_case(&cur, "_PRECISE")) { 1024bf215546Sopenharmony_ci *pcur = cur; 1025bf215546Sopenharmony_ci *precise = 1; 1026bf215546Sopenharmony_ci } 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_ci if (!is_digit_alpha_underscore(cur)) 1029bf215546Sopenharmony_ci return TRUE; 1030bf215546Sopenharmony_ci } 1031bf215546Sopenharmony_ci 1032bf215546Sopenharmony_ci return FALSE; 1033bf215546Sopenharmony_ci} 1034bf215546Sopenharmony_ci 1035bf215546Sopenharmony_cistatic boolean 1036bf215546Sopenharmony_ciparse_instruction( 1037bf215546Sopenharmony_ci struct translate_ctx *ctx, 1038bf215546Sopenharmony_ci boolean has_label ) 1039bf215546Sopenharmony_ci{ 1040bf215546Sopenharmony_ci int i; 1041bf215546Sopenharmony_ci uint saturate = 0; 1042bf215546Sopenharmony_ci uint precise = 0; 1043bf215546Sopenharmony_ci const struct tgsi_opcode_info *info; 1044bf215546Sopenharmony_ci struct tgsi_full_instruction inst; 1045bf215546Sopenharmony_ci const char *cur; 1046bf215546Sopenharmony_ci uint advance; 1047bf215546Sopenharmony_ci 1048bf215546Sopenharmony_ci inst = tgsi_default_full_instruction(); 1049bf215546Sopenharmony_ci 1050bf215546Sopenharmony_ci /* Parse instruction name. 1051bf215546Sopenharmony_ci */ 1052bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1053bf215546Sopenharmony_ci for (i = 0; i < TGSI_OPCODE_LAST; i++) { 1054bf215546Sopenharmony_ci cur = ctx->cur; 1055bf215546Sopenharmony_ci 1056bf215546Sopenharmony_ci info = tgsi_get_opcode_info( i ); 1057bf215546Sopenharmony_ci if (match_inst(&cur, &saturate, &precise, info)) { 1058bf215546Sopenharmony_ci if (info->num_dst + info->num_src + info->is_tex == 0) { 1059bf215546Sopenharmony_ci ctx->cur = cur; 1060bf215546Sopenharmony_ci break; 1061bf215546Sopenharmony_ci } 1062bf215546Sopenharmony_ci else if (*cur == '\0' || eat_white( &cur )) { 1063bf215546Sopenharmony_ci ctx->cur = cur; 1064bf215546Sopenharmony_ci break; 1065bf215546Sopenharmony_ci } 1066bf215546Sopenharmony_ci } 1067bf215546Sopenharmony_ci } 1068bf215546Sopenharmony_ci if (i == TGSI_OPCODE_LAST) { 1069bf215546Sopenharmony_ci if (has_label) 1070bf215546Sopenharmony_ci report_error( ctx, "Unknown opcode" ); 1071bf215546Sopenharmony_ci else 1072bf215546Sopenharmony_ci report_error( ctx, "Expected `DCL', `IMM' or a label" ); 1073bf215546Sopenharmony_ci return FALSE; 1074bf215546Sopenharmony_ci } 1075bf215546Sopenharmony_ci 1076bf215546Sopenharmony_ci inst.Instruction.Opcode = i; 1077bf215546Sopenharmony_ci inst.Instruction.Saturate = saturate; 1078bf215546Sopenharmony_ci inst.Instruction.Precise = precise; 1079bf215546Sopenharmony_ci inst.Instruction.NumDstRegs = info->num_dst; 1080bf215546Sopenharmony_ci inst.Instruction.NumSrcRegs = info->num_src; 1081bf215546Sopenharmony_ci 1082bf215546Sopenharmony_ci if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { 1083bf215546Sopenharmony_ci /* 1084bf215546Sopenharmony_ci * These are not considered tex opcodes here (no additional 1085bf215546Sopenharmony_ci * target argument) however we're required to set the Texture 1086bf215546Sopenharmony_ci * bit so we can set the number of tex offsets. 1087bf215546Sopenharmony_ci */ 1088bf215546Sopenharmony_ci inst.Instruction.Texture = 1; 1089bf215546Sopenharmony_ci inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; 1090bf215546Sopenharmony_ci } 1091bf215546Sopenharmony_ci 1092bf215546Sopenharmony_ci if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || 1093bf215546Sopenharmony_ci i == TGSI_OPCODE_RESQ) { 1094bf215546Sopenharmony_ci inst.Instruction.Memory = 1; 1095bf215546Sopenharmony_ci inst.Memory.Qualifier = 0; 1096bf215546Sopenharmony_ci } 1097bf215546Sopenharmony_ci 1098bf215546Sopenharmony_ci assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS); 1099bf215546Sopenharmony_ci assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS); 1100bf215546Sopenharmony_ci 1101bf215546Sopenharmony_ci /* Parse instruction operands. 1102bf215546Sopenharmony_ci */ 1103bf215546Sopenharmony_ci for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { 1104bf215546Sopenharmony_ci if (i > 0) { 1105bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1106bf215546Sopenharmony_ci if (*ctx->cur != ',') { 1107bf215546Sopenharmony_ci report_error( ctx, "Expected `,'" ); 1108bf215546Sopenharmony_ci return FALSE; 1109bf215546Sopenharmony_ci } 1110bf215546Sopenharmony_ci ctx->cur++; 1111bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1112bf215546Sopenharmony_ci } 1113bf215546Sopenharmony_ci 1114bf215546Sopenharmony_ci if (i < info->num_dst) { 1115bf215546Sopenharmony_ci if (!parse_dst_operand( ctx, &inst.Dst[i] )) 1116bf215546Sopenharmony_ci return FALSE; 1117bf215546Sopenharmony_ci } 1118bf215546Sopenharmony_ci else if (i < info->num_dst + info->num_src) { 1119bf215546Sopenharmony_ci if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) 1120bf215546Sopenharmony_ci return FALSE; 1121bf215546Sopenharmony_ci } 1122bf215546Sopenharmony_ci else { 1123bf215546Sopenharmony_ci uint j; 1124bf215546Sopenharmony_ci 1125bf215546Sopenharmony_ci for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { 1126bf215546Sopenharmony_ci if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { 1127bf215546Sopenharmony_ci inst.Instruction.Texture = 1; 1128bf215546Sopenharmony_ci inst.Texture.Texture = j; 1129bf215546Sopenharmony_ci break; 1130bf215546Sopenharmony_ci } 1131bf215546Sopenharmony_ci } 1132bf215546Sopenharmony_ci if (j == TGSI_TEXTURE_COUNT) { 1133bf215546Sopenharmony_ci report_error( ctx, "Expected texture target" ); 1134bf215546Sopenharmony_ci return FALSE; 1135bf215546Sopenharmony_ci } 1136bf215546Sopenharmony_ci } 1137bf215546Sopenharmony_ci } 1138bf215546Sopenharmony_ci 1139bf215546Sopenharmony_ci cur = ctx->cur; 1140bf215546Sopenharmony_ci eat_opt_white( &cur ); 1141bf215546Sopenharmony_ci for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) { 1142bf215546Sopenharmony_ci cur++; 1143bf215546Sopenharmony_ci eat_opt_white( &cur ); 1144bf215546Sopenharmony_ci ctx->cur = cur; 1145bf215546Sopenharmony_ci if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] )) 1146bf215546Sopenharmony_ci return FALSE; 1147bf215546Sopenharmony_ci cur = ctx->cur; 1148bf215546Sopenharmony_ci eat_opt_white( &cur ); 1149bf215546Sopenharmony_ci } 1150bf215546Sopenharmony_ci inst.Texture.NumOffsets = i; 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_ci cur = ctx->cur; 1153bf215546Sopenharmony_ci eat_opt_white(&cur); 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_ci for (; inst.Instruction.Memory && *cur == ','; 1156bf215546Sopenharmony_ci ctx->cur = cur, eat_opt_white(&cur)) { 1157bf215546Sopenharmony_ci int j; 1158bf215546Sopenharmony_ci 1159bf215546Sopenharmony_ci cur++; 1160bf215546Sopenharmony_ci eat_opt_white(&cur); 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_ci j = str_match_name_from_array(&cur, tgsi_memory_names, 1163bf215546Sopenharmony_ci ARRAY_SIZE(tgsi_memory_names)); 1164bf215546Sopenharmony_ci if (j >= 0) { 1165bf215546Sopenharmony_ci inst.Memory.Qualifier |= 1U << j; 1166bf215546Sopenharmony_ci continue; 1167bf215546Sopenharmony_ci } 1168bf215546Sopenharmony_ci 1169bf215546Sopenharmony_ci j = str_match_name_from_array(&cur, tgsi_texture_names, 1170bf215546Sopenharmony_ci ARRAY_SIZE(tgsi_texture_names)); 1171bf215546Sopenharmony_ci if (j >= 0) { 1172bf215546Sopenharmony_ci inst.Memory.Texture = j; 1173bf215546Sopenharmony_ci continue; 1174bf215546Sopenharmony_ci } 1175bf215546Sopenharmony_ci 1176bf215546Sopenharmony_ci j = str_match_format(&cur); 1177bf215546Sopenharmony_ci if (j >= 0) { 1178bf215546Sopenharmony_ci inst.Memory.Format = j; 1179bf215546Sopenharmony_ci continue; 1180bf215546Sopenharmony_ci } 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_ci ctx->cur = cur; 1183bf215546Sopenharmony_ci report_error(ctx, "Expected memory qualifier, texture target, or format\n"); 1184bf215546Sopenharmony_ci return FALSE; 1185bf215546Sopenharmony_ci } 1186bf215546Sopenharmony_ci 1187bf215546Sopenharmony_ci cur = ctx->cur; 1188bf215546Sopenharmony_ci eat_opt_white( &cur ); 1189bf215546Sopenharmony_ci if (info->is_branch && *cur == ':') { 1190bf215546Sopenharmony_ci uint target; 1191bf215546Sopenharmony_ci 1192bf215546Sopenharmony_ci cur++; 1193bf215546Sopenharmony_ci eat_opt_white( &cur ); 1194bf215546Sopenharmony_ci if (!parse_uint( &cur, &target )) { 1195bf215546Sopenharmony_ci report_error( ctx, "Expected a label" ); 1196bf215546Sopenharmony_ci return FALSE; 1197bf215546Sopenharmony_ci } 1198bf215546Sopenharmony_ci inst.Instruction.Label = 1; 1199bf215546Sopenharmony_ci inst.Label.Label = target; 1200bf215546Sopenharmony_ci ctx->cur = cur; 1201bf215546Sopenharmony_ci } 1202bf215546Sopenharmony_ci 1203bf215546Sopenharmony_ci advance = tgsi_build_full_instruction( 1204bf215546Sopenharmony_ci &inst, 1205bf215546Sopenharmony_ci ctx->tokens_cur, 1206bf215546Sopenharmony_ci ctx->header, 1207bf215546Sopenharmony_ci (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1208bf215546Sopenharmony_ci if (advance == 0) 1209bf215546Sopenharmony_ci return FALSE; 1210bf215546Sopenharmony_ci ctx->tokens_cur += advance; 1211bf215546Sopenharmony_ci 1212bf215546Sopenharmony_ci return TRUE; 1213bf215546Sopenharmony_ci} 1214bf215546Sopenharmony_ci 1215bf215546Sopenharmony_ci/* parses a 4-touple of the form {x, y, z, w} 1216bf215546Sopenharmony_ci * where x, y, z, w are numbers */ 1217bf215546Sopenharmony_cistatic boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type, 1218bf215546Sopenharmony_ci union tgsi_immediate_data *values) 1219bf215546Sopenharmony_ci{ 1220bf215546Sopenharmony_ci unsigned i; 1221bf215546Sopenharmony_ci int ret; 1222bf215546Sopenharmony_ci 1223bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1224bf215546Sopenharmony_ci if (*ctx->cur != '{') { 1225bf215546Sopenharmony_ci report_error( ctx, "Expected `{'" ); 1226bf215546Sopenharmony_ci return FALSE; 1227bf215546Sopenharmony_ci } 1228bf215546Sopenharmony_ci ctx->cur++; 1229bf215546Sopenharmony_ci for (i = 0; i < 4; i++) { 1230bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1231bf215546Sopenharmony_ci if (i > 0) { 1232bf215546Sopenharmony_ci if (*ctx->cur != ',') { 1233bf215546Sopenharmony_ci report_error( ctx, "Expected `,'" ); 1234bf215546Sopenharmony_ci return FALSE; 1235bf215546Sopenharmony_ci } 1236bf215546Sopenharmony_ci ctx->cur++; 1237bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1238bf215546Sopenharmony_ci } 1239bf215546Sopenharmony_ci 1240bf215546Sopenharmony_ci switch (type) { 1241bf215546Sopenharmony_ci case TGSI_IMM_FLOAT64: 1242bf215546Sopenharmony_ci ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1243bf215546Sopenharmony_ci i++; 1244bf215546Sopenharmony_ci break; 1245bf215546Sopenharmony_ci case TGSI_IMM_INT64: 1246bf215546Sopenharmony_ci ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1247bf215546Sopenharmony_ci i++; 1248bf215546Sopenharmony_ci break; 1249bf215546Sopenharmony_ci case TGSI_IMM_UINT64: 1250bf215546Sopenharmony_ci ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1251bf215546Sopenharmony_ci i++; 1252bf215546Sopenharmony_ci break; 1253bf215546Sopenharmony_ci case TGSI_IMM_FLOAT32: 1254bf215546Sopenharmony_ci ret = parse_float(&ctx->cur, &values[i].Float); 1255bf215546Sopenharmony_ci break; 1256bf215546Sopenharmony_ci case TGSI_IMM_UINT32: 1257bf215546Sopenharmony_ci ret = parse_uint(&ctx->cur, &values[i].Uint); 1258bf215546Sopenharmony_ci break; 1259bf215546Sopenharmony_ci case TGSI_IMM_INT32: 1260bf215546Sopenharmony_ci ret = parse_int(&ctx->cur, &values[i].Int); 1261bf215546Sopenharmony_ci break; 1262bf215546Sopenharmony_ci default: 1263bf215546Sopenharmony_ci assert(0); 1264bf215546Sopenharmony_ci ret = FALSE; 1265bf215546Sopenharmony_ci break; 1266bf215546Sopenharmony_ci } 1267bf215546Sopenharmony_ci 1268bf215546Sopenharmony_ci if (!ret) { 1269bf215546Sopenharmony_ci report_error( ctx, "Expected immediate constant" ); 1270bf215546Sopenharmony_ci return FALSE; 1271bf215546Sopenharmony_ci } 1272bf215546Sopenharmony_ci } 1273bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1274bf215546Sopenharmony_ci if (*ctx->cur != '}') { 1275bf215546Sopenharmony_ci report_error( ctx, "Expected `}'" ); 1276bf215546Sopenharmony_ci return FALSE; 1277bf215546Sopenharmony_ci } 1278bf215546Sopenharmony_ci ctx->cur++; 1279bf215546Sopenharmony_ci 1280bf215546Sopenharmony_ci return TRUE; 1281bf215546Sopenharmony_ci} 1282bf215546Sopenharmony_ci 1283bf215546Sopenharmony_cistatic boolean parse_declaration( struct translate_ctx *ctx ) 1284bf215546Sopenharmony_ci{ 1285bf215546Sopenharmony_ci struct tgsi_full_declaration decl; 1286bf215546Sopenharmony_ci uint file; 1287bf215546Sopenharmony_ci struct parsed_dcl_bracket brackets[2]; 1288bf215546Sopenharmony_ci int num_brackets; 1289bf215546Sopenharmony_ci uint writemask; 1290bf215546Sopenharmony_ci const char *cur, *cur2; 1291bf215546Sopenharmony_ci uint advance; 1292bf215546Sopenharmony_ci boolean is_vs_input; 1293bf215546Sopenharmony_ci 1294bf215546Sopenharmony_ci if (!eat_white( &ctx->cur )) { 1295bf215546Sopenharmony_ci report_error( ctx, "Syntax error" ); 1296bf215546Sopenharmony_ci return FALSE; 1297bf215546Sopenharmony_ci } 1298bf215546Sopenharmony_ci if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) 1299bf215546Sopenharmony_ci return FALSE; 1300bf215546Sopenharmony_ci if (!parse_opt_writemask( ctx, &writemask )) 1301bf215546Sopenharmony_ci return FALSE; 1302bf215546Sopenharmony_ci 1303bf215546Sopenharmony_ci decl = tgsi_default_full_declaration(); 1304bf215546Sopenharmony_ci decl.Declaration.File = file; 1305bf215546Sopenharmony_ci decl.Declaration.UsageMask = writemask; 1306bf215546Sopenharmony_ci 1307bf215546Sopenharmony_ci if (num_brackets == 1) { 1308bf215546Sopenharmony_ci decl.Range.First = brackets[0].first; 1309bf215546Sopenharmony_ci decl.Range.Last = brackets[0].last; 1310bf215546Sopenharmony_ci } else { 1311bf215546Sopenharmony_ci decl.Range.First = brackets[1].first; 1312bf215546Sopenharmony_ci decl.Range.Last = brackets[1].last; 1313bf215546Sopenharmony_ci 1314bf215546Sopenharmony_ci decl.Declaration.Dimension = 1; 1315bf215546Sopenharmony_ci decl.Dim.Index2D = brackets[0].first; 1316bf215546Sopenharmony_ci } 1317bf215546Sopenharmony_ci 1318bf215546Sopenharmony_ci is_vs_input = (file == TGSI_FILE_INPUT && 1319bf215546Sopenharmony_ci ctx->processor == PIPE_SHADER_VERTEX); 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_ci cur = ctx->cur; 1322bf215546Sopenharmony_ci eat_opt_white( &cur ); 1323bf215546Sopenharmony_ci if (*cur == ',') { 1324bf215546Sopenharmony_ci cur2 = cur; 1325bf215546Sopenharmony_ci cur2++; 1326bf215546Sopenharmony_ci eat_opt_white( &cur2 ); 1327bf215546Sopenharmony_ci if (str_match_nocase_whole( &cur2, "ARRAY" )) { 1328bf215546Sopenharmony_ci int arrayid; 1329bf215546Sopenharmony_ci if (*cur2 != '(') { 1330bf215546Sopenharmony_ci report_error( ctx, "Expected `('" ); 1331bf215546Sopenharmony_ci return FALSE; 1332bf215546Sopenharmony_ci } 1333bf215546Sopenharmony_ci cur2++; 1334bf215546Sopenharmony_ci eat_opt_white( &cur2 ); 1335bf215546Sopenharmony_ci if (!parse_int( &cur2, &arrayid )) { 1336bf215546Sopenharmony_ci report_error( ctx, "Expected `,'" ); 1337bf215546Sopenharmony_ci return FALSE; 1338bf215546Sopenharmony_ci } 1339bf215546Sopenharmony_ci eat_opt_white( &cur2 ); 1340bf215546Sopenharmony_ci if (*cur2 != ')') { 1341bf215546Sopenharmony_ci report_error( ctx, "Expected `)'" ); 1342bf215546Sopenharmony_ci return FALSE; 1343bf215546Sopenharmony_ci } 1344bf215546Sopenharmony_ci cur2++; 1345bf215546Sopenharmony_ci decl.Declaration.Array = 1; 1346bf215546Sopenharmony_ci decl.Array.ArrayID = arrayid; 1347bf215546Sopenharmony_ci ctx->cur = cur = cur2; 1348bf215546Sopenharmony_ci } 1349bf215546Sopenharmony_ci } 1350bf215546Sopenharmony_ci 1351bf215546Sopenharmony_ci if (*cur == ',' && !is_vs_input) { 1352bf215546Sopenharmony_ci uint i, j; 1353bf215546Sopenharmony_ci 1354bf215546Sopenharmony_ci cur++; 1355bf215546Sopenharmony_ci eat_opt_white( &cur ); 1356bf215546Sopenharmony_ci if (file == TGSI_FILE_IMAGE) { 1357bf215546Sopenharmony_ci for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { 1358bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { 1359bf215546Sopenharmony_ci decl.Image.Resource = i; 1360bf215546Sopenharmony_ci break; 1361bf215546Sopenharmony_ci } 1362bf215546Sopenharmony_ci } 1363bf215546Sopenharmony_ci if (i == TGSI_TEXTURE_COUNT) { 1364bf215546Sopenharmony_ci report_error(ctx, "Expected texture target"); 1365bf215546Sopenharmony_ci return FALSE; 1366bf215546Sopenharmony_ci } 1367bf215546Sopenharmony_ci 1368bf215546Sopenharmony_ci cur2 = cur; 1369bf215546Sopenharmony_ci eat_opt_white(&cur2); 1370bf215546Sopenharmony_ci while (*cur2 == ',') { 1371bf215546Sopenharmony_ci cur2++; 1372bf215546Sopenharmony_ci eat_opt_white(&cur2); 1373bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur2, "RAW")) { 1374bf215546Sopenharmony_ci decl.Image.Raw = 1; 1375bf215546Sopenharmony_ci 1376bf215546Sopenharmony_ci } else if (str_match_nocase_whole(&cur2, "WR")) { 1377bf215546Sopenharmony_ci decl.Image.Writable = 1; 1378bf215546Sopenharmony_ci 1379bf215546Sopenharmony_ci } else { 1380bf215546Sopenharmony_ci int format = str_match_format(&cur2); 1381bf215546Sopenharmony_ci if (format < 0) 1382bf215546Sopenharmony_ci break; 1383bf215546Sopenharmony_ci 1384bf215546Sopenharmony_ci decl.Image.Format = format; 1385bf215546Sopenharmony_ci } 1386bf215546Sopenharmony_ci cur = cur2; 1387bf215546Sopenharmony_ci eat_opt_white(&cur2); 1388bf215546Sopenharmony_ci } 1389bf215546Sopenharmony_ci 1390bf215546Sopenharmony_ci ctx->cur = cur; 1391bf215546Sopenharmony_ci 1392bf215546Sopenharmony_ci } else if (file == TGSI_FILE_SAMPLER_VIEW) { 1393bf215546Sopenharmony_ci for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { 1394bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { 1395bf215546Sopenharmony_ci decl.SamplerView.Resource = i; 1396bf215546Sopenharmony_ci break; 1397bf215546Sopenharmony_ci } 1398bf215546Sopenharmony_ci } 1399bf215546Sopenharmony_ci if (i == TGSI_TEXTURE_COUNT) { 1400bf215546Sopenharmony_ci report_error(ctx, "Expected texture target"); 1401bf215546Sopenharmony_ci return FALSE; 1402bf215546Sopenharmony_ci } 1403bf215546Sopenharmony_ci eat_opt_white( &cur ); 1404bf215546Sopenharmony_ci if (*cur != ',') { 1405bf215546Sopenharmony_ci report_error( ctx, "Expected `,'" ); 1406bf215546Sopenharmony_ci return FALSE; 1407bf215546Sopenharmony_ci } 1408bf215546Sopenharmony_ci ++cur; 1409bf215546Sopenharmony_ci eat_opt_white( &cur ); 1410bf215546Sopenharmony_ci for (j = 0; j < 4; ++j) { 1411bf215546Sopenharmony_ci for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) { 1412bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) { 1413bf215546Sopenharmony_ci switch (j) { 1414bf215546Sopenharmony_ci case 0: 1415bf215546Sopenharmony_ci decl.SamplerView.ReturnTypeX = i; 1416bf215546Sopenharmony_ci break; 1417bf215546Sopenharmony_ci case 1: 1418bf215546Sopenharmony_ci decl.SamplerView.ReturnTypeY = i; 1419bf215546Sopenharmony_ci break; 1420bf215546Sopenharmony_ci case 2: 1421bf215546Sopenharmony_ci decl.SamplerView.ReturnTypeZ = i; 1422bf215546Sopenharmony_ci break; 1423bf215546Sopenharmony_ci case 3: 1424bf215546Sopenharmony_ci decl.SamplerView.ReturnTypeW = i; 1425bf215546Sopenharmony_ci break; 1426bf215546Sopenharmony_ci default: 1427bf215546Sopenharmony_ci assert(0); 1428bf215546Sopenharmony_ci } 1429bf215546Sopenharmony_ci break; 1430bf215546Sopenharmony_ci } 1431bf215546Sopenharmony_ci } 1432bf215546Sopenharmony_ci if (i == TGSI_RETURN_TYPE_COUNT) { 1433bf215546Sopenharmony_ci if (j == 0 || j > 2) { 1434bf215546Sopenharmony_ci report_error(ctx, "Expected type name"); 1435bf215546Sopenharmony_ci return FALSE; 1436bf215546Sopenharmony_ci } 1437bf215546Sopenharmony_ci break; 1438bf215546Sopenharmony_ci } else { 1439bf215546Sopenharmony_ci cur2 = cur; 1440bf215546Sopenharmony_ci eat_opt_white( &cur2 ); 1441bf215546Sopenharmony_ci if (*cur2 == ',') { 1442bf215546Sopenharmony_ci cur2++; 1443bf215546Sopenharmony_ci eat_opt_white( &cur2 ); 1444bf215546Sopenharmony_ci cur = cur2; 1445bf215546Sopenharmony_ci continue; 1446bf215546Sopenharmony_ci } else 1447bf215546Sopenharmony_ci break; 1448bf215546Sopenharmony_ci } 1449bf215546Sopenharmony_ci } 1450bf215546Sopenharmony_ci if (j < 4) { 1451bf215546Sopenharmony_ci decl.SamplerView.ReturnTypeY = 1452bf215546Sopenharmony_ci decl.SamplerView.ReturnTypeZ = 1453bf215546Sopenharmony_ci decl.SamplerView.ReturnTypeW = 1454bf215546Sopenharmony_ci decl.SamplerView.ReturnTypeX; 1455bf215546Sopenharmony_ci } 1456bf215546Sopenharmony_ci ctx->cur = cur; 1457bf215546Sopenharmony_ci } else if (file == TGSI_FILE_BUFFER) { 1458bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur, "ATOMIC")) { 1459bf215546Sopenharmony_ci decl.Declaration.Atomic = 1; 1460bf215546Sopenharmony_ci ctx->cur = cur; 1461bf215546Sopenharmony_ci } 1462bf215546Sopenharmony_ci } else if (file == TGSI_FILE_MEMORY) { 1463bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur, "GLOBAL")) { 1464bf215546Sopenharmony_ci /* Note this is a no-op global is the default */ 1465bf215546Sopenharmony_ci decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL; 1466bf215546Sopenharmony_ci ctx->cur = cur; 1467bf215546Sopenharmony_ci } else if (str_match_nocase_whole(&cur, "SHARED")) { 1468bf215546Sopenharmony_ci decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED; 1469bf215546Sopenharmony_ci ctx->cur = cur; 1470bf215546Sopenharmony_ci } else if (str_match_nocase_whole(&cur, "PRIVATE")) { 1471bf215546Sopenharmony_ci decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE; 1472bf215546Sopenharmony_ci ctx->cur = cur; 1473bf215546Sopenharmony_ci } else if (str_match_nocase_whole(&cur, "INPUT")) { 1474bf215546Sopenharmony_ci decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT; 1475bf215546Sopenharmony_ci ctx->cur = cur; 1476bf215546Sopenharmony_ci } 1477bf215546Sopenharmony_ci } else { 1478bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur, "LOCAL")) { 1479bf215546Sopenharmony_ci decl.Declaration.Local = 1; 1480bf215546Sopenharmony_ci ctx->cur = cur; 1481bf215546Sopenharmony_ci } 1482bf215546Sopenharmony_ci 1483bf215546Sopenharmony_ci cur = ctx->cur; 1484bf215546Sopenharmony_ci eat_opt_white( &cur ); 1485bf215546Sopenharmony_ci if (*cur == ',') { 1486bf215546Sopenharmony_ci cur++; 1487bf215546Sopenharmony_ci eat_opt_white( &cur ); 1488bf215546Sopenharmony_ci 1489bf215546Sopenharmony_ci for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { 1490bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) { 1491bf215546Sopenharmony_ci uint index; 1492bf215546Sopenharmony_ci 1493bf215546Sopenharmony_ci cur2 = cur; 1494bf215546Sopenharmony_ci eat_opt_white( &cur2 ); 1495bf215546Sopenharmony_ci if (*cur2 == '[') { 1496bf215546Sopenharmony_ci cur2++; 1497bf215546Sopenharmony_ci eat_opt_white( &cur2 ); 1498bf215546Sopenharmony_ci if (!parse_uint( &cur2, &index )) { 1499bf215546Sopenharmony_ci report_error( ctx, "Expected literal integer" ); 1500bf215546Sopenharmony_ci return FALSE; 1501bf215546Sopenharmony_ci } 1502bf215546Sopenharmony_ci eat_opt_white( &cur2 ); 1503bf215546Sopenharmony_ci if (*cur2 != ']') { 1504bf215546Sopenharmony_ci report_error( ctx, "Expected `]'" ); 1505bf215546Sopenharmony_ci return FALSE; 1506bf215546Sopenharmony_ci } 1507bf215546Sopenharmony_ci cur2++; 1508bf215546Sopenharmony_ci 1509bf215546Sopenharmony_ci decl.Semantic.Index = index; 1510bf215546Sopenharmony_ci 1511bf215546Sopenharmony_ci cur = cur2; 1512bf215546Sopenharmony_ci } 1513bf215546Sopenharmony_ci 1514bf215546Sopenharmony_ci decl.Declaration.Semantic = 1; 1515bf215546Sopenharmony_ci decl.Semantic.Name = i; 1516bf215546Sopenharmony_ci 1517bf215546Sopenharmony_ci ctx->cur = cur; 1518bf215546Sopenharmony_ci break; 1519bf215546Sopenharmony_ci } 1520bf215546Sopenharmony_ci } 1521bf215546Sopenharmony_ci } 1522bf215546Sopenharmony_ci } 1523bf215546Sopenharmony_ci } 1524bf215546Sopenharmony_ci 1525bf215546Sopenharmony_ci cur = ctx->cur; 1526bf215546Sopenharmony_ci eat_opt_white( &cur ); 1527bf215546Sopenharmony_ci if (*cur == ',' && 1528bf215546Sopenharmony_ci file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) { 1529bf215546Sopenharmony_ci cur++; 1530bf215546Sopenharmony_ci eat_opt_white(&cur); 1531bf215546Sopenharmony_ci if (str_match_nocase_whole(&cur, "STREAM")) { 1532bf215546Sopenharmony_ci uint stream[4]; 1533bf215546Sopenharmony_ci 1534bf215546Sopenharmony_ci eat_opt_white(&cur); 1535bf215546Sopenharmony_ci if (*cur != '(') { 1536bf215546Sopenharmony_ci report_error(ctx, "Expected '('"); 1537bf215546Sopenharmony_ci return FALSE; 1538bf215546Sopenharmony_ci } 1539bf215546Sopenharmony_ci cur++; 1540bf215546Sopenharmony_ci 1541bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 1542bf215546Sopenharmony_ci eat_opt_white(&cur); 1543bf215546Sopenharmony_ci if (!parse_uint(&cur, &stream[i])) { 1544bf215546Sopenharmony_ci report_error(ctx, "Expected literal integer"); 1545bf215546Sopenharmony_ci return FALSE; 1546bf215546Sopenharmony_ci } 1547bf215546Sopenharmony_ci 1548bf215546Sopenharmony_ci eat_opt_white(&cur); 1549bf215546Sopenharmony_ci if (i < 3) { 1550bf215546Sopenharmony_ci if (*cur != ',') { 1551bf215546Sopenharmony_ci report_error(ctx, "Expected ','"); 1552bf215546Sopenharmony_ci return FALSE; 1553bf215546Sopenharmony_ci } 1554bf215546Sopenharmony_ci cur++; 1555bf215546Sopenharmony_ci } 1556bf215546Sopenharmony_ci } 1557bf215546Sopenharmony_ci 1558bf215546Sopenharmony_ci if (*cur != ')') { 1559bf215546Sopenharmony_ci report_error(ctx, "Expected ')'"); 1560bf215546Sopenharmony_ci return FALSE; 1561bf215546Sopenharmony_ci } 1562bf215546Sopenharmony_ci cur++; 1563bf215546Sopenharmony_ci 1564bf215546Sopenharmony_ci decl.Semantic.StreamX = stream[0]; 1565bf215546Sopenharmony_ci decl.Semantic.StreamY = stream[1]; 1566bf215546Sopenharmony_ci decl.Semantic.StreamZ = stream[2]; 1567bf215546Sopenharmony_ci decl.Semantic.StreamW = stream[3]; 1568bf215546Sopenharmony_ci 1569bf215546Sopenharmony_ci ctx->cur = cur; 1570bf215546Sopenharmony_ci } 1571bf215546Sopenharmony_ci } 1572bf215546Sopenharmony_ci 1573bf215546Sopenharmony_ci cur = ctx->cur; 1574bf215546Sopenharmony_ci eat_opt_white( &cur ); 1575bf215546Sopenharmony_ci if (*cur == ',' && !is_vs_input) { 1576bf215546Sopenharmony_ci uint i; 1577bf215546Sopenharmony_ci 1578bf215546Sopenharmony_ci cur++; 1579bf215546Sopenharmony_ci eat_opt_white( &cur ); 1580bf215546Sopenharmony_ci for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { 1581bf215546Sopenharmony_ci if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) { 1582bf215546Sopenharmony_ci decl.Declaration.Interpolate = 1; 1583bf215546Sopenharmony_ci decl.Interp.Interpolate = i; 1584bf215546Sopenharmony_ci 1585bf215546Sopenharmony_ci ctx->cur = cur; 1586bf215546Sopenharmony_ci break; 1587bf215546Sopenharmony_ci } 1588bf215546Sopenharmony_ci } 1589bf215546Sopenharmony_ci } 1590bf215546Sopenharmony_ci 1591bf215546Sopenharmony_ci cur = ctx->cur; 1592bf215546Sopenharmony_ci eat_opt_white( &cur ); 1593bf215546Sopenharmony_ci if (*cur == ',' && !is_vs_input) { 1594bf215546Sopenharmony_ci uint i; 1595bf215546Sopenharmony_ci 1596bf215546Sopenharmony_ci cur++; 1597bf215546Sopenharmony_ci eat_opt_white( &cur ); 1598bf215546Sopenharmony_ci for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) { 1599bf215546Sopenharmony_ci if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) { 1600bf215546Sopenharmony_ci decl.Interp.Location = i; 1601bf215546Sopenharmony_ci 1602bf215546Sopenharmony_ci ctx->cur = cur; 1603bf215546Sopenharmony_ci break; 1604bf215546Sopenharmony_ci } 1605bf215546Sopenharmony_ci } 1606bf215546Sopenharmony_ci } 1607bf215546Sopenharmony_ci 1608bf215546Sopenharmony_ci cur = ctx->cur; 1609bf215546Sopenharmony_ci eat_opt_white( &cur ); 1610bf215546Sopenharmony_ci if (*cur == ',' && !is_vs_input) { 1611bf215546Sopenharmony_ci cur++; 1612bf215546Sopenharmony_ci eat_opt_white( &cur ); 1613bf215546Sopenharmony_ci if (str_match_nocase_whole( &cur, tgsi_invariant_name )) { 1614bf215546Sopenharmony_ci decl.Declaration.Invariant = 1; 1615bf215546Sopenharmony_ci ctx->cur = cur; 1616bf215546Sopenharmony_ci } else { 1617bf215546Sopenharmony_ci report_error( ctx, "Expected semantic, interpolate attribute, or invariant "); 1618bf215546Sopenharmony_ci return FALSE; 1619bf215546Sopenharmony_ci } 1620bf215546Sopenharmony_ci } 1621bf215546Sopenharmony_ci 1622bf215546Sopenharmony_ci advance = tgsi_build_full_declaration( 1623bf215546Sopenharmony_ci &decl, 1624bf215546Sopenharmony_ci ctx->tokens_cur, 1625bf215546Sopenharmony_ci ctx->header, 1626bf215546Sopenharmony_ci (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1627bf215546Sopenharmony_ci 1628bf215546Sopenharmony_ci if (advance == 0) 1629bf215546Sopenharmony_ci return FALSE; 1630bf215546Sopenharmony_ci ctx->tokens_cur += advance; 1631bf215546Sopenharmony_ci 1632bf215546Sopenharmony_ci return TRUE; 1633bf215546Sopenharmony_ci} 1634bf215546Sopenharmony_ci 1635bf215546Sopenharmony_cistatic boolean parse_immediate( struct translate_ctx *ctx ) 1636bf215546Sopenharmony_ci{ 1637bf215546Sopenharmony_ci struct tgsi_full_immediate imm; 1638bf215546Sopenharmony_ci uint advance; 1639bf215546Sopenharmony_ci uint type; 1640bf215546Sopenharmony_ci 1641bf215546Sopenharmony_ci if (*ctx->cur == '[') { 1642bf215546Sopenharmony_ci uint uindex; 1643bf215546Sopenharmony_ci 1644bf215546Sopenharmony_ci ++ctx->cur; 1645bf215546Sopenharmony_ci 1646bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1647bf215546Sopenharmony_ci if (!parse_uint( &ctx->cur, &uindex )) { 1648bf215546Sopenharmony_ci report_error( ctx, "Expected literal unsigned integer" ); 1649bf215546Sopenharmony_ci return FALSE; 1650bf215546Sopenharmony_ci } 1651bf215546Sopenharmony_ci 1652bf215546Sopenharmony_ci if (uindex != ctx->num_immediates) { 1653bf215546Sopenharmony_ci report_error( ctx, "Immediates must be sorted" ); 1654bf215546Sopenharmony_ci return FALSE; 1655bf215546Sopenharmony_ci } 1656bf215546Sopenharmony_ci 1657bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1658bf215546Sopenharmony_ci if (*ctx->cur != ']') { 1659bf215546Sopenharmony_ci report_error( ctx, "Expected `]'" ); 1660bf215546Sopenharmony_ci return FALSE; 1661bf215546Sopenharmony_ci } 1662bf215546Sopenharmony_ci 1663bf215546Sopenharmony_ci ctx->cur++; 1664bf215546Sopenharmony_ci } 1665bf215546Sopenharmony_ci 1666bf215546Sopenharmony_ci if (!eat_white( &ctx->cur )) { 1667bf215546Sopenharmony_ci report_error( ctx, "Syntax error" ); 1668bf215546Sopenharmony_ci return FALSE; 1669bf215546Sopenharmony_ci } 1670bf215546Sopenharmony_ci for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) { 1671bf215546Sopenharmony_ci if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type])) 1672bf215546Sopenharmony_ci break; 1673bf215546Sopenharmony_ci } 1674bf215546Sopenharmony_ci if (type == ARRAY_SIZE(tgsi_immediate_type_names)) { 1675bf215546Sopenharmony_ci report_error( ctx, "Expected immediate type" ); 1676bf215546Sopenharmony_ci return FALSE; 1677bf215546Sopenharmony_ci } 1678bf215546Sopenharmony_ci 1679bf215546Sopenharmony_ci imm = tgsi_default_full_immediate(); 1680bf215546Sopenharmony_ci imm.Immediate.NrTokens += 4; 1681bf215546Sopenharmony_ci imm.Immediate.DataType = type; 1682bf215546Sopenharmony_ci parse_immediate_data(ctx, type, imm.u); 1683bf215546Sopenharmony_ci 1684bf215546Sopenharmony_ci advance = tgsi_build_full_immediate( 1685bf215546Sopenharmony_ci &imm, 1686bf215546Sopenharmony_ci ctx->tokens_cur, 1687bf215546Sopenharmony_ci ctx->header, 1688bf215546Sopenharmony_ci (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1689bf215546Sopenharmony_ci if (advance == 0) 1690bf215546Sopenharmony_ci return FALSE; 1691bf215546Sopenharmony_ci ctx->tokens_cur += advance; 1692bf215546Sopenharmony_ci 1693bf215546Sopenharmony_ci ctx->num_immediates++; 1694bf215546Sopenharmony_ci 1695bf215546Sopenharmony_ci return TRUE; 1696bf215546Sopenharmony_ci} 1697bf215546Sopenharmony_ci 1698bf215546Sopenharmony_cistatic boolean 1699bf215546Sopenharmony_ciparse_primitive( const char **pcur, uint *primitive ) 1700bf215546Sopenharmony_ci{ 1701bf215546Sopenharmony_ci uint i; 1702bf215546Sopenharmony_ci 1703bf215546Sopenharmony_ci for (i = 0; i < PIPE_PRIM_MAX; i++) { 1704bf215546Sopenharmony_ci const char *cur = *pcur; 1705bf215546Sopenharmony_ci 1706bf215546Sopenharmony_ci if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) { 1707bf215546Sopenharmony_ci *primitive = i; 1708bf215546Sopenharmony_ci *pcur = cur; 1709bf215546Sopenharmony_ci return TRUE; 1710bf215546Sopenharmony_ci } 1711bf215546Sopenharmony_ci } 1712bf215546Sopenharmony_ci return FALSE; 1713bf215546Sopenharmony_ci} 1714bf215546Sopenharmony_ci 1715bf215546Sopenharmony_cistatic boolean 1716bf215546Sopenharmony_ciparse_fs_coord_origin( const char **pcur, uint *fs_coord_origin ) 1717bf215546Sopenharmony_ci{ 1718bf215546Sopenharmony_ci uint i; 1719bf215546Sopenharmony_ci 1720bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) { 1721bf215546Sopenharmony_ci const char *cur = *pcur; 1722bf215546Sopenharmony_ci 1723bf215546Sopenharmony_ci if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) { 1724bf215546Sopenharmony_ci *fs_coord_origin = i; 1725bf215546Sopenharmony_ci *pcur = cur; 1726bf215546Sopenharmony_ci return TRUE; 1727bf215546Sopenharmony_ci } 1728bf215546Sopenharmony_ci } 1729bf215546Sopenharmony_ci return FALSE; 1730bf215546Sopenharmony_ci} 1731bf215546Sopenharmony_ci 1732bf215546Sopenharmony_cistatic boolean 1733bf215546Sopenharmony_ciparse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center ) 1734bf215546Sopenharmony_ci{ 1735bf215546Sopenharmony_ci uint i; 1736bf215546Sopenharmony_ci 1737bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) { 1738bf215546Sopenharmony_ci const char *cur = *pcur; 1739bf215546Sopenharmony_ci 1740bf215546Sopenharmony_ci if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) { 1741bf215546Sopenharmony_ci *fs_coord_pixel_center = i; 1742bf215546Sopenharmony_ci *pcur = cur; 1743bf215546Sopenharmony_ci return TRUE; 1744bf215546Sopenharmony_ci } 1745bf215546Sopenharmony_ci } 1746bf215546Sopenharmony_ci return FALSE; 1747bf215546Sopenharmony_ci} 1748bf215546Sopenharmony_ci 1749bf215546Sopenharmony_cistatic boolean 1750bf215546Sopenharmony_ciparse_property_next_shader( const char **pcur, uint *next_shader ) 1751bf215546Sopenharmony_ci{ 1752bf215546Sopenharmony_ci uint i; 1753bf215546Sopenharmony_ci 1754bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) { 1755bf215546Sopenharmony_ci const char *cur = *pcur; 1756bf215546Sopenharmony_ci 1757bf215546Sopenharmony_ci if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) { 1758bf215546Sopenharmony_ci *next_shader = i; 1759bf215546Sopenharmony_ci *pcur = cur; 1760bf215546Sopenharmony_ci return TRUE; 1761bf215546Sopenharmony_ci } 1762bf215546Sopenharmony_ci } 1763bf215546Sopenharmony_ci return FALSE; 1764bf215546Sopenharmony_ci} 1765bf215546Sopenharmony_ci 1766bf215546Sopenharmony_cistatic boolean parse_property( struct translate_ctx *ctx ) 1767bf215546Sopenharmony_ci{ 1768bf215546Sopenharmony_ci struct tgsi_full_property prop; 1769bf215546Sopenharmony_ci uint property_name; 1770bf215546Sopenharmony_ci uint values[8]; 1771bf215546Sopenharmony_ci uint advance; 1772bf215546Sopenharmony_ci char id[64]; 1773bf215546Sopenharmony_ci 1774bf215546Sopenharmony_ci if (!eat_white( &ctx->cur )) { 1775bf215546Sopenharmony_ci report_error( ctx, "Syntax error" ); 1776bf215546Sopenharmony_ci return FALSE; 1777bf215546Sopenharmony_ci } 1778bf215546Sopenharmony_ci if (!parse_identifier( &ctx->cur, id, sizeof(id) )) { 1779bf215546Sopenharmony_ci report_error( ctx, "Syntax error" ); 1780bf215546Sopenharmony_ci return FALSE; 1781bf215546Sopenharmony_ci } 1782bf215546Sopenharmony_ci for (property_name = 0; property_name < TGSI_PROPERTY_COUNT; 1783bf215546Sopenharmony_ci ++property_name) { 1784bf215546Sopenharmony_ci if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) { 1785bf215546Sopenharmony_ci break; 1786bf215546Sopenharmony_ci } 1787bf215546Sopenharmony_ci } 1788bf215546Sopenharmony_ci if (property_name >= TGSI_PROPERTY_COUNT) { 1789bf215546Sopenharmony_ci debug_printf( "\nError: Unknown property : '%s'", id ); 1790bf215546Sopenharmony_ci return FALSE; 1791bf215546Sopenharmony_ci } 1792bf215546Sopenharmony_ci 1793bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1794bf215546Sopenharmony_ci switch(property_name) { 1795bf215546Sopenharmony_ci case TGSI_PROPERTY_GS_INPUT_PRIM: 1796bf215546Sopenharmony_ci case TGSI_PROPERTY_GS_OUTPUT_PRIM: 1797bf215546Sopenharmony_ci if (!parse_primitive(&ctx->cur, &values[0] )) { 1798bf215546Sopenharmony_ci report_error( ctx, "Unknown primitive name as property!" ); 1799bf215546Sopenharmony_ci return FALSE; 1800bf215546Sopenharmony_ci } 1801bf215546Sopenharmony_ci if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM && 1802bf215546Sopenharmony_ci ctx->processor == PIPE_SHADER_GEOMETRY) { 1803bf215546Sopenharmony_ci ctx->implied_array_size = u_vertices_per_prim(values[0]); 1804bf215546Sopenharmony_ci } 1805bf215546Sopenharmony_ci break; 1806bf215546Sopenharmony_ci case TGSI_PROPERTY_FS_COORD_ORIGIN: 1807bf215546Sopenharmony_ci if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) { 1808bf215546Sopenharmony_ci report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" ); 1809bf215546Sopenharmony_ci return FALSE; 1810bf215546Sopenharmony_ci } 1811bf215546Sopenharmony_ci break; 1812bf215546Sopenharmony_ci case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: 1813bf215546Sopenharmony_ci if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) { 1814bf215546Sopenharmony_ci report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" ); 1815bf215546Sopenharmony_ci return FALSE; 1816bf215546Sopenharmony_ci } 1817bf215546Sopenharmony_ci break; 1818bf215546Sopenharmony_ci case TGSI_PROPERTY_NEXT_SHADER: 1819bf215546Sopenharmony_ci if (!parse_property_next_shader(&ctx->cur, &values[0] )) { 1820bf215546Sopenharmony_ci report_error( ctx, "Unknown next shader property value." ); 1821bf215546Sopenharmony_ci return FALSE; 1822bf215546Sopenharmony_ci } 1823bf215546Sopenharmony_ci break; 1824bf215546Sopenharmony_ci case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS: 1825bf215546Sopenharmony_ci default: 1826bf215546Sopenharmony_ci if (!parse_uint(&ctx->cur, &values[0] )) { 1827bf215546Sopenharmony_ci report_error( ctx, "Expected unsigned integer as property!" ); 1828bf215546Sopenharmony_ci return FALSE; 1829bf215546Sopenharmony_ci } 1830bf215546Sopenharmony_ci } 1831bf215546Sopenharmony_ci 1832bf215546Sopenharmony_ci prop = tgsi_default_full_property(); 1833bf215546Sopenharmony_ci prop.Property.PropertyName = property_name; 1834bf215546Sopenharmony_ci prop.Property.NrTokens += 1; 1835bf215546Sopenharmony_ci prop.u[0].Data = values[0]; 1836bf215546Sopenharmony_ci 1837bf215546Sopenharmony_ci advance = tgsi_build_full_property( 1838bf215546Sopenharmony_ci &prop, 1839bf215546Sopenharmony_ci ctx->tokens_cur, 1840bf215546Sopenharmony_ci ctx->header, 1841bf215546Sopenharmony_ci (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1842bf215546Sopenharmony_ci if (advance == 0) 1843bf215546Sopenharmony_ci return FALSE; 1844bf215546Sopenharmony_ci ctx->tokens_cur += advance; 1845bf215546Sopenharmony_ci 1846bf215546Sopenharmony_ci return TRUE; 1847bf215546Sopenharmony_ci} 1848bf215546Sopenharmony_ci 1849bf215546Sopenharmony_ci 1850bf215546Sopenharmony_cistatic boolean translate( struct translate_ctx *ctx ) 1851bf215546Sopenharmony_ci{ 1852bf215546Sopenharmony_ci eat_opt_white( &ctx->cur ); 1853bf215546Sopenharmony_ci if (!parse_header( ctx )) 1854bf215546Sopenharmony_ci return FALSE; 1855bf215546Sopenharmony_ci 1856bf215546Sopenharmony_ci if (ctx->processor == PIPE_SHADER_TESS_CTRL || 1857bf215546Sopenharmony_ci ctx->processor == PIPE_SHADER_TESS_EVAL) 1858bf215546Sopenharmony_ci ctx->implied_array_size = 32; 1859bf215546Sopenharmony_ci 1860bf215546Sopenharmony_ci while (*ctx->cur != '\0') { 1861bf215546Sopenharmony_ci uint label_val = 0; 1862bf215546Sopenharmony_ci if (!eat_white( &ctx->cur )) { 1863bf215546Sopenharmony_ci report_error( ctx, "Syntax error" ); 1864bf215546Sopenharmony_ci return FALSE; 1865bf215546Sopenharmony_ci } 1866bf215546Sopenharmony_ci 1867bf215546Sopenharmony_ci if (*ctx->cur == '\0') 1868bf215546Sopenharmony_ci break; 1869bf215546Sopenharmony_ci if (parse_label( ctx, &label_val )) { 1870bf215546Sopenharmony_ci if (!parse_instruction( ctx, TRUE )) 1871bf215546Sopenharmony_ci return FALSE; 1872bf215546Sopenharmony_ci } 1873bf215546Sopenharmony_ci else if (str_match_nocase_whole( &ctx->cur, "DCL" )) { 1874bf215546Sopenharmony_ci if (!parse_declaration( ctx )) 1875bf215546Sopenharmony_ci return FALSE; 1876bf215546Sopenharmony_ci } 1877bf215546Sopenharmony_ci else if (str_match_nocase_whole( &ctx->cur, "IMM" )) { 1878bf215546Sopenharmony_ci if (!parse_immediate( ctx )) 1879bf215546Sopenharmony_ci return FALSE; 1880bf215546Sopenharmony_ci } 1881bf215546Sopenharmony_ci else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) { 1882bf215546Sopenharmony_ci if (!parse_property( ctx )) 1883bf215546Sopenharmony_ci return FALSE; 1884bf215546Sopenharmony_ci } 1885bf215546Sopenharmony_ci else if (!parse_instruction( ctx, FALSE )) { 1886bf215546Sopenharmony_ci return FALSE; 1887bf215546Sopenharmony_ci } 1888bf215546Sopenharmony_ci } 1889bf215546Sopenharmony_ci 1890bf215546Sopenharmony_ci return TRUE; 1891bf215546Sopenharmony_ci} 1892bf215546Sopenharmony_ci 1893bf215546Sopenharmony_ciboolean 1894bf215546Sopenharmony_citgsi_text_translate( 1895bf215546Sopenharmony_ci const char *text, 1896bf215546Sopenharmony_ci struct tgsi_token *tokens, 1897bf215546Sopenharmony_ci uint num_tokens ) 1898bf215546Sopenharmony_ci{ 1899bf215546Sopenharmony_ci struct translate_ctx ctx = {0}; 1900bf215546Sopenharmony_ci 1901bf215546Sopenharmony_ci ctx.text = text; 1902bf215546Sopenharmony_ci ctx.cur = text; 1903bf215546Sopenharmony_ci ctx.tokens = tokens; 1904bf215546Sopenharmony_ci ctx.tokens_cur = tokens; 1905bf215546Sopenharmony_ci ctx.tokens_end = tokens + num_tokens; 1906bf215546Sopenharmony_ci 1907bf215546Sopenharmony_ci if (!translate( &ctx )) 1908bf215546Sopenharmony_ci return FALSE; 1909bf215546Sopenharmony_ci 1910bf215546Sopenharmony_ci return tgsi_sanity_check( tokens ); 1911bf215546Sopenharmony_ci} 1912