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