gallium: add a new register file - immediate array
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_text.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "util/u_debug.h"
29 #include "util/u_memory.h"
30 #include "util/u_prim.h"
31 #include "pipe/p_defines.h"
32 #include "util/u_inlines.h"
33 #include "tgsi_text.h"
34 #include "tgsi_build.h"
35 #include "tgsi_info.h"
36 #include "tgsi_parse.h"
37 #include "tgsi_sanity.h"
38 #include "tgsi_util.h"
39
40 static boolean is_alpha_underscore( const char *cur )
41 {
42 return
43 (*cur >= 'a' && *cur <= 'z') ||
44 (*cur >= 'A' && *cur <= 'Z') ||
45 *cur == '_';
46 }
47
48 static boolean is_digit( const char *cur )
49 {
50 return *cur >= '0' && *cur <= '9';
51 }
52
53 static boolean is_digit_alpha_underscore( const char *cur )
54 {
55 return is_digit( cur ) || is_alpha_underscore( cur );
56 }
57
58 static char uprcase( char c )
59 {
60 if (c >= 'a' && c <= 'z')
61 return c += 'A' - 'a';
62 return c;
63 }
64
65 /*
66 * Ignore case of str1 and assume str1 is already uppercase.
67 * Return TRUE iff str1 and str2 are equal.
68 */
69 static int
70 streq_nocase_uprcase(const char *str1,
71 const char *str2)
72 {
73 while (*str1 && *str2) {
74 if (*str1 != uprcase(*str2))
75 return FALSE;
76 str1++;
77 str2++;
78 }
79 return *str1 == 0 && *str2 == 0;
80 }
81
82 static boolean str_match_no_case( const char **pcur, const char *str )
83 {
84 const char *cur = *pcur;
85
86 while (*str != '\0' && *str == uprcase( *cur )) {
87 str++;
88 cur++;
89 }
90 if (*str == '\0') {
91 *pcur = cur;
92 return TRUE;
93 }
94 return FALSE;
95 }
96
97 /* Eat zero or more whitespaces.
98 */
99 static void eat_opt_white( const char **pcur )
100 {
101 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
102 (*pcur)++;
103 }
104
105 /* Eat one or more whitespaces.
106 * Return TRUE if at least one whitespace eaten.
107 */
108 static boolean eat_white( const char **pcur )
109 {
110 const char *cur = *pcur;
111
112 eat_opt_white( pcur );
113 return *pcur > cur;
114 }
115
116 /* Parse unsigned integer.
117 * No checks for overflow.
118 */
119 static boolean parse_uint( const char **pcur, uint *val )
120 {
121 const char *cur = *pcur;
122
123 if (is_digit( cur )) {
124 *val = *cur++ - '0';
125 while (is_digit( cur ))
126 *val = *val * 10 + *cur++ - '0';
127 *pcur = cur;
128 return TRUE;
129 }
130 return FALSE;
131 }
132
133 static boolean parse_identifier( const char **pcur, char *ret )
134 {
135 const char *cur = *pcur;
136 int i = 0;
137 if (is_alpha_underscore( cur )) {
138 ret[i++] = *cur++;
139 while (is_alpha_underscore( cur ))
140 ret[i++] = *cur++;
141 ret[i++] = '\0';
142 *pcur = cur;
143 return TRUE;
144 }
145 return FALSE;
146 }
147
148 /* Parse floating point.
149 */
150 static boolean parse_float( const char **pcur, float *val )
151 {
152 const char *cur = *pcur;
153 boolean integral_part = FALSE;
154 boolean fractional_part = FALSE;
155
156 *val = (float) atof( cur );
157
158 if (*cur == '-' || *cur == '+')
159 cur++;
160 if (is_digit( cur )) {
161 cur++;
162 integral_part = TRUE;
163 while (is_digit( cur ))
164 cur++;
165 }
166 if (*cur == '.') {
167 cur++;
168 if (is_digit( cur )) {
169 cur++;
170 fractional_part = TRUE;
171 while (is_digit( cur ))
172 cur++;
173 }
174 }
175 if (!integral_part && !fractional_part)
176 return FALSE;
177 if (uprcase( *cur ) == 'E') {
178 cur++;
179 if (*cur == '-' || *cur == '+')
180 cur++;
181 if (is_digit( cur )) {
182 cur++;
183 while (is_digit( cur ))
184 cur++;
185 }
186 else
187 return FALSE;
188 }
189 *pcur = cur;
190 return TRUE;
191 }
192
193 struct translate_ctx
194 {
195 const char *text;
196 const char *cur;
197 struct tgsi_token *tokens;
198 struct tgsi_token *tokens_cur;
199 struct tgsi_token *tokens_end;
200 struct tgsi_header *header;
201 unsigned processor : 4;
202 int implied_array_size : 5;
203 };
204
205 static void report_error( struct translate_ctx *ctx, const char *msg )
206 {
207 int line = 1;
208 int column = 1;
209 const char *itr = ctx->text;
210
211 while (itr != ctx->cur) {
212 if (*itr == '\n') {
213 column = 1;
214 ++line;
215 }
216 ++column;
217 ++itr;
218 }
219
220 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
221 }
222
223 /* Parse shader header.
224 * Return TRUE for one of the following headers.
225 * FRAG
226 * GEOM
227 * VERT
228 */
229 static boolean parse_header( struct translate_ctx *ctx )
230 {
231 uint processor;
232
233 if (str_match_no_case( &ctx->cur, "FRAG" ))
234 processor = TGSI_PROCESSOR_FRAGMENT;
235 else if (str_match_no_case( &ctx->cur, "VERT" ))
236 processor = TGSI_PROCESSOR_VERTEX;
237 else if (str_match_no_case( &ctx->cur, "GEOM" ))
238 processor = TGSI_PROCESSOR_GEOMETRY;
239 else {
240 report_error( ctx, "Unknown header" );
241 return FALSE;
242 }
243
244 if (ctx->tokens_cur >= ctx->tokens_end)
245 return FALSE;
246 ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
247 *ctx->header = tgsi_build_header();
248
249 if (ctx->tokens_cur >= ctx->tokens_end)
250 return FALSE;
251 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
252 ctx->processor = processor;
253
254 return TRUE;
255 }
256
257 static boolean parse_label( struct translate_ctx *ctx, uint *val )
258 {
259 const char *cur = ctx->cur;
260
261 if (parse_uint( &cur, val )) {
262 eat_opt_white( &cur );
263 if (*cur == ':') {
264 cur++;
265 ctx->cur = cur;
266 return TRUE;
267 }
268 }
269 return FALSE;
270 }
271
272 static const char *file_names[TGSI_FILE_COUNT] =
273 {
274 "NULL",
275 "CONST",
276 "IN",
277 "OUT",
278 "TEMP",
279 "SAMP",
280 "ADDR",
281 "IMM",
282 "PRED",
283 "SV",
284 "IMMX"
285 };
286
287 static boolean
288 parse_file( const char **pcur, uint *file )
289 {
290 uint i;
291
292 for (i = 0; i < TGSI_FILE_COUNT; i++) {
293 const char *cur = *pcur;
294
295 if (str_match_no_case( &cur, file_names[i] )) {
296 if (!is_digit_alpha_underscore( cur )) {
297 *pcur = cur;
298 *file = i;
299 return TRUE;
300 }
301 }
302 }
303 return FALSE;
304 }
305
306 static boolean
307 parse_opt_writemask(
308 struct translate_ctx *ctx,
309 uint *writemask )
310 {
311 const char *cur;
312
313 cur = ctx->cur;
314 eat_opt_white( &cur );
315 if (*cur == '.') {
316 cur++;
317 *writemask = TGSI_WRITEMASK_NONE;
318 eat_opt_white( &cur );
319 if (uprcase( *cur ) == 'X') {
320 cur++;
321 *writemask |= TGSI_WRITEMASK_X;
322 }
323 if (uprcase( *cur ) == 'Y') {
324 cur++;
325 *writemask |= TGSI_WRITEMASK_Y;
326 }
327 if (uprcase( *cur ) == 'Z') {
328 cur++;
329 *writemask |= TGSI_WRITEMASK_Z;
330 }
331 if (uprcase( *cur ) == 'W') {
332 cur++;
333 *writemask |= TGSI_WRITEMASK_W;
334 }
335
336 if (*writemask == TGSI_WRITEMASK_NONE) {
337 report_error( ctx, "Writemask expected" );
338 return FALSE;
339 }
340
341 ctx->cur = cur;
342 }
343 else {
344 *writemask = TGSI_WRITEMASK_XYZW;
345 }
346 return TRUE;
347 }
348
349 static boolean
350 parse_register_dst( struct translate_ctx *ctx,
351 uint *file,
352 int *index );
353
354 struct parsed_src_bracket {
355 int index;
356
357 uint ind_file;
358 int ind_index;
359 uint ind_comp;
360 };
361
362
363 static boolean
364 parse_register_src_bracket(
365 struct translate_ctx *ctx,
366 struct parsed_src_bracket *brackets)
367 {
368 const char *cur;
369 uint uindex;
370
371 memset(brackets, 0, sizeof(struct parsed_src_bracket));
372
373 eat_opt_white( &ctx->cur );
374
375 cur = ctx->cur;
376 if (parse_file( &cur, &brackets->ind_file )) {
377 if (!parse_register_dst( ctx, &brackets->ind_file,
378 &brackets->ind_index ))
379 return FALSE;
380 eat_opt_white( &ctx->cur );
381
382 if (*ctx->cur == '.') {
383 ctx->cur++;
384 eat_opt_white(&ctx->cur);
385
386 switch (uprcase(*ctx->cur)) {
387 case 'X':
388 brackets->ind_comp = TGSI_SWIZZLE_X;
389 break;
390 case 'Y':
391 brackets->ind_comp = TGSI_SWIZZLE_Y;
392 break;
393 case 'Z':
394 brackets->ind_comp = TGSI_SWIZZLE_Z;
395 break;
396 case 'W':
397 brackets->ind_comp = TGSI_SWIZZLE_W;
398 break;
399 default:
400 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
401 return FALSE;
402 }
403 ctx->cur++;
404 eat_opt_white(&ctx->cur);
405 }
406
407 if (*ctx->cur == '+' || *ctx->cur == '-') {
408 boolean negate;
409
410 negate = *ctx->cur == '-';
411 ctx->cur++;
412 eat_opt_white( &ctx->cur );
413 if (!parse_uint( &ctx->cur, &uindex )) {
414 report_error( ctx, "Expected literal unsigned integer" );
415 return FALSE;
416 }
417 if (negate)
418 brackets->index = -(int) uindex;
419 else
420 brackets->index = (int) uindex;
421 }
422 else {
423 brackets->index = 0;
424 }
425 }
426 else {
427 if (!parse_uint( &ctx->cur, &uindex )) {
428 report_error( ctx, "Expected literal unsigned integer" );
429 return FALSE;
430 }
431 brackets->index = (int) uindex;
432 brackets->ind_file = TGSI_FILE_NULL;
433 brackets->ind_index = 0;
434 }
435 eat_opt_white( &ctx->cur );
436 if (*ctx->cur != ']') {
437 report_error( ctx, "Expected `]'" );
438 return FALSE;
439 }
440 ctx->cur++;
441 return TRUE;
442 }
443
444 static boolean
445 parse_opt_register_src_bracket(
446 struct translate_ctx *ctx,
447 struct parsed_src_bracket *brackets,
448 int *parsed_brackets)
449 {
450 const char *cur = ctx->cur;
451
452 *parsed_brackets = 0;
453
454 eat_opt_white( &cur );
455 if (cur[0] == '[') {
456 ++cur;
457 ctx->cur = cur;
458
459 if (!parse_register_src_bracket(ctx, brackets))
460 return FALSE;
461
462 *parsed_brackets = 1;
463 }
464
465 return TRUE;
466 }
467
468 /* <register_file_bracket> ::= <file> `['
469 */
470 static boolean
471 parse_register_file_bracket(
472 struct translate_ctx *ctx,
473 uint *file )
474 {
475 if (!parse_file( &ctx->cur, file )) {
476 report_error( ctx, "Unknown register file" );
477 return FALSE;
478 }
479 eat_opt_white( &ctx->cur );
480 if (*ctx->cur != '[') {
481 report_error( ctx, "Expected `['" );
482 return FALSE;
483 }
484 ctx->cur++;
485 return TRUE;
486 }
487
488 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
489 */
490 static boolean
491 parse_register_file_bracket_index(
492 struct translate_ctx *ctx,
493 uint *file,
494 int *index )
495 {
496 uint uindex;
497
498 if (!parse_register_file_bracket( ctx, file ))
499 return FALSE;
500 eat_opt_white( &ctx->cur );
501 if (!parse_uint( &ctx->cur, &uindex )) {
502 report_error( ctx, "Expected literal unsigned integer" );
503 return FALSE;
504 }
505 *index = (int) uindex;
506 return TRUE;
507 }
508
509 /* Parse source register operand.
510 * <register_src> ::= <register_file_bracket_index> `]' |
511 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
512 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
513 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
514 */
515 static boolean
516 parse_register_src(
517 struct translate_ctx *ctx,
518 uint *file,
519 struct parsed_src_bracket *brackets)
520 {
521
522 brackets->ind_comp = TGSI_SWIZZLE_X;
523 if (!parse_register_file_bracket( ctx, file ))
524 return FALSE;
525 if (!parse_register_src_bracket( ctx, brackets ))
526 return FALSE;
527
528 return TRUE;
529 }
530
531 struct parsed_dcl_bracket {
532 uint first;
533 uint last;
534 };
535
536 static boolean
537 parse_register_dcl_bracket(
538 struct translate_ctx *ctx,
539 struct parsed_dcl_bracket *bracket)
540 {
541 uint uindex;
542 memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
543
544 eat_opt_white( &ctx->cur );
545
546 if (!parse_uint( &ctx->cur, &uindex )) {
547 /* it can be an empty bracket [] which means its range
548 * is from 0 to some implied size */
549 if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
550 bracket->first = 0;
551 bracket->last = ctx->implied_array_size - 1;
552 goto cleanup;
553 }
554 report_error( ctx, "Expected literal unsigned integer" );
555 return FALSE;
556 }
557 bracket->first = uindex;
558
559 eat_opt_white( &ctx->cur );
560
561 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
562 uint uindex;
563
564 ctx->cur += 2;
565 eat_opt_white( &ctx->cur );
566 if (!parse_uint( &ctx->cur, &uindex )) {
567 report_error( ctx, "Expected literal integer" );
568 return FALSE;
569 }
570 bracket->last = (int) uindex;
571 eat_opt_white( &ctx->cur );
572 }
573 else {
574 bracket->last = bracket->first;
575 }
576
577 cleanup:
578 if (*ctx->cur != ']') {
579 report_error( ctx, "Expected `]' or `..'" );
580 return FALSE;
581 }
582 ctx->cur++;
583 return TRUE;
584 }
585
586 /* Parse register declaration.
587 * <register_dcl> ::= <register_file_bracket_index> `]' |
588 * <register_file_bracket_index> `..' <index> `]'
589 */
590 static boolean
591 parse_register_dcl(
592 struct translate_ctx *ctx,
593 uint *file,
594 struct parsed_dcl_bracket *brackets,
595 int *num_brackets)
596 {
597 const char *cur;
598
599 *num_brackets = 0;
600
601 if (!parse_register_file_bracket( ctx, file ))
602 return FALSE;
603 if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
604 return FALSE;
605
606 *num_brackets = 1;
607
608 cur = ctx->cur;
609 eat_opt_white( &cur );
610
611 if (cur[0] == '[') {
612 ++cur;
613 ctx->cur = cur;
614 if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
615 return FALSE;
616 /* for geometry shader we don't really care about
617 * the first brackets it's always the size of the
618 * input primitive. so we want to declare just
619 * the index relevant to the semantics which is in
620 * the second bracket */
621 if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
622 brackets[0] = brackets[1];
623 *num_brackets = 1;
624 } else {
625 *num_brackets = 2;
626 }
627 }
628
629 return TRUE;
630 }
631
632
633 /* Parse destination register operand.
634 * <register_dst> ::= <register_file_bracket_index> `]'
635 */
636 static boolean
637 parse_register_dst(
638 struct translate_ctx *ctx,
639 uint *file,
640 int *index )
641 {
642 if (!parse_register_file_bracket_index( ctx, file, index ))
643 return FALSE;
644 eat_opt_white( &ctx->cur );
645 if (*ctx->cur != ']') {
646 report_error( ctx, "Expected `]'" );
647 return FALSE;
648 }
649 ctx->cur++;
650 return TRUE;
651 }
652
653 static boolean
654 parse_dst_operand(
655 struct translate_ctx *ctx,
656 struct tgsi_full_dst_register *dst )
657 {
658 uint file;
659 int index;
660 uint writemask;
661 const char *cur;
662
663 if (!parse_register_dst( ctx, &file, &index ))
664 return FALSE;
665
666 cur = ctx->cur;
667 eat_opt_white( &cur );
668
669 if (!parse_opt_writemask( ctx, &writemask ))
670 return FALSE;
671
672 dst->Register.File = file;
673 dst->Register.Index = index;
674 dst->Register.WriteMask = writemask;
675 return TRUE;
676 }
677
678 static boolean
679 parse_optional_swizzle(
680 struct translate_ctx *ctx,
681 uint swizzle[4],
682 boolean *parsed_swizzle )
683 {
684 const char *cur = ctx->cur;
685
686 *parsed_swizzle = FALSE;
687
688 eat_opt_white( &cur );
689 if (*cur == '.') {
690 uint i;
691
692 cur++;
693 eat_opt_white( &cur );
694 for (i = 0; i < 4; i++) {
695 if (uprcase( *cur ) == 'X')
696 swizzle[i] = TGSI_SWIZZLE_X;
697 else if (uprcase( *cur ) == 'Y')
698 swizzle[i] = TGSI_SWIZZLE_Y;
699 else if (uprcase( *cur ) == 'Z')
700 swizzle[i] = TGSI_SWIZZLE_Z;
701 else if (uprcase( *cur ) == 'W')
702 swizzle[i] = TGSI_SWIZZLE_W;
703 else {
704 report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
705 return FALSE;
706 }
707 cur++;
708 }
709 *parsed_swizzle = TRUE;
710 ctx->cur = cur;
711 }
712 return TRUE;
713 }
714
715 static boolean
716 parse_src_operand(
717 struct translate_ctx *ctx,
718 struct tgsi_full_src_register *src )
719 {
720 uint file;
721 uint swizzle[4];
722 boolean parsed_swizzle;
723 struct parsed_src_bracket bracket[2];
724 int parsed_opt_brackets;
725
726 if (*ctx->cur == '-') {
727 ctx->cur++;
728 eat_opt_white( &ctx->cur );
729 src->Register.Negate = 1;
730 }
731
732 if (*ctx->cur == '|') {
733 ctx->cur++;
734 eat_opt_white( &ctx->cur );
735 src->Register.Absolute = 1;
736 }
737
738 if (!parse_register_src(ctx, &file, &bracket[0]))
739 return FALSE;
740 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
741 return FALSE;
742
743 src->Register.File = file;
744 if (parsed_opt_brackets) {
745 src->Register.Dimension = 1;
746 src->Dimension.Indirect = 0;
747 src->Dimension.Dimension = 0;
748 src->Dimension.Index = bracket[0].index;
749 bracket[0] = bracket[1];
750 }
751 src->Register.Index = bracket[0].index;
752 if (bracket[0].ind_file != TGSI_FILE_NULL) {
753 src->Register.Indirect = 1;
754 src->Indirect.File = bracket[0].ind_file;
755 src->Indirect.Index = bracket[0].ind_index;
756 src->Indirect.SwizzleX = bracket[0].ind_comp;
757 src->Indirect.SwizzleY = bracket[0].ind_comp;
758 src->Indirect.SwizzleZ = bracket[0].ind_comp;
759 src->Indirect.SwizzleW = bracket[0].ind_comp;
760 }
761
762 /* Parse optional swizzle.
763 */
764 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
765 if (parsed_swizzle) {
766 src->Register.SwizzleX = swizzle[0];
767 src->Register.SwizzleY = swizzle[1];
768 src->Register.SwizzleZ = swizzle[2];
769 src->Register.SwizzleW = swizzle[3];
770 }
771 }
772
773 if (src->Register.Absolute) {
774 eat_opt_white( &ctx->cur );
775 if (*ctx->cur != '|') {
776 report_error( ctx, "Expected `|'" );
777 return FALSE;
778 }
779 ctx->cur++;
780 }
781
782
783 return TRUE;
784 }
785
786 static const char *texture_names[TGSI_TEXTURE_COUNT] =
787 {
788 "UNKNOWN",
789 "1D",
790 "2D",
791 "3D",
792 "CUBE",
793 "RECT",
794 "SHADOW1D",
795 "SHADOW2D",
796 "SHADOWRECT"
797 };
798
799 static boolean
800 match_inst_mnemonic(const char **pcur,
801 const struct tgsi_opcode_info *info)
802 {
803 if (str_match_no_case(pcur, info->mnemonic)) {
804 return TRUE;
805 }
806 return FALSE;
807 }
808
809 static boolean
810 parse_instruction(
811 struct translate_ctx *ctx,
812 boolean has_label )
813 {
814 uint i;
815 uint saturate = TGSI_SAT_NONE;
816 const struct tgsi_opcode_info *info;
817 struct tgsi_full_instruction inst;
818 uint advance;
819
820 inst = tgsi_default_full_instruction();
821
822 /* Parse predicate.
823 */
824 eat_opt_white( &ctx->cur );
825 if (*ctx->cur == '(') {
826 uint file;
827 int index;
828 uint swizzle[4];
829 boolean parsed_swizzle;
830
831 inst.Instruction.Predicate = 1;
832
833 ctx->cur++;
834 if (*ctx->cur == '!') {
835 ctx->cur++;
836 inst.Predicate.Negate = 1;
837 }
838
839 if (!parse_register_dst( ctx, &file, &index ))
840 return FALSE;
841
842 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
843 if (parsed_swizzle) {
844 inst.Predicate.SwizzleX = swizzle[0];
845 inst.Predicate.SwizzleY = swizzle[1];
846 inst.Predicate.SwizzleZ = swizzle[2];
847 inst.Predicate.SwizzleW = swizzle[3];
848 }
849 }
850
851 if (*ctx->cur != ')') {
852 report_error( ctx, "Expected `)'" );
853 return FALSE;
854 }
855
856 ctx->cur++;
857 }
858
859 /* Parse instruction name.
860 */
861 eat_opt_white( &ctx->cur );
862 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
863 const char *cur = ctx->cur;
864
865 info = tgsi_get_opcode_info( i );
866 if (match_inst_mnemonic(&cur, info)) {
867 if (str_match_no_case( &cur, "_SATNV" ))
868 saturate = TGSI_SAT_MINUS_PLUS_ONE;
869 else if (str_match_no_case( &cur, "_SAT" ))
870 saturate = TGSI_SAT_ZERO_ONE;
871
872 if (info->num_dst + info->num_src + info->is_tex == 0) {
873 if (!is_digit_alpha_underscore( cur )) {
874 ctx->cur = cur;
875 break;
876 }
877 }
878 else if (*cur == '\0' || eat_white( &cur )) {
879 ctx->cur = cur;
880 break;
881 }
882 }
883 }
884 if (i == TGSI_OPCODE_LAST) {
885 if (has_label)
886 report_error( ctx, "Unknown opcode" );
887 else
888 report_error( ctx, "Expected `DCL', `IMM' or a label" );
889 return FALSE;
890 }
891
892 inst.Instruction.Opcode = i;
893 inst.Instruction.Saturate = saturate;
894 inst.Instruction.NumDstRegs = info->num_dst;
895 inst.Instruction.NumSrcRegs = info->num_src;
896
897 /* Parse instruction operands.
898 */
899 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
900 if (i > 0) {
901 eat_opt_white( &ctx->cur );
902 if (*ctx->cur != ',') {
903 report_error( ctx, "Expected `,'" );
904 return FALSE;
905 }
906 ctx->cur++;
907 eat_opt_white( &ctx->cur );
908 }
909
910 if (i < info->num_dst) {
911 if (!parse_dst_operand( ctx, &inst.Dst[i] ))
912 return FALSE;
913 }
914 else if (i < info->num_dst + info->num_src) {
915 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
916 return FALSE;
917 }
918 else {
919 uint j;
920
921 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
922 if (str_match_no_case( &ctx->cur, texture_names[j] )) {
923 if (!is_digit_alpha_underscore( ctx->cur )) {
924 inst.Instruction.Texture = 1;
925 inst.Texture.Texture = j;
926 break;
927 }
928 }
929 }
930 if (j == TGSI_TEXTURE_COUNT) {
931 report_error( ctx, "Expected texture target" );
932 return FALSE;
933 }
934 }
935 }
936
937 if (info->is_branch) {
938 uint target;
939
940 eat_opt_white( &ctx->cur );
941 if (*ctx->cur != ':') {
942 report_error( ctx, "Expected `:'" );
943 return FALSE;
944 }
945 ctx->cur++;
946 eat_opt_white( &ctx->cur );
947 if (!parse_uint( &ctx->cur, &target )) {
948 report_error( ctx, "Expected a label" );
949 return FALSE;
950 }
951 inst.Instruction.Label = 1;
952 inst.Label.Label = target;
953 }
954
955 advance = tgsi_build_full_instruction(
956 &inst,
957 ctx->tokens_cur,
958 ctx->header,
959 (uint) (ctx->tokens_end - ctx->tokens_cur) );
960 if (advance == 0)
961 return FALSE;
962 ctx->tokens_cur += advance;
963
964 return TRUE;
965 }
966
967 static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
968 {
969 "POSITION",
970 "COLOR",
971 "BCOLOR",
972 "FOG",
973 "PSIZE",
974 "GENERIC",
975 "NORMAL",
976 "FACE",
977 "EDGEFLAG",
978 "PRIM_ID",
979 "INSTANCEID"
980 };
981
982 static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
983 {
984 "CONSTANT",
985 "LINEAR",
986 "PERSPECTIVE"
987 };
988
989
990 /* parses a 4-touple of the form {x, y, z, w}
991 * where x, y, z, w are numbers */
992 static boolean parse_immediate_data(struct translate_ctx *ctx,
993 float *values)
994 {
995 unsigned i;
996
997 eat_opt_white( &ctx->cur );
998 if (*ctx->cur != '{') {
999 report_error( ctx, "Expected `{'" );
1000 return FALSE;
1001 }
1002 ctx->cur++;
1003 for (i = 0; i < 4; i++) {
1004 eat_opt_white( &ctx->cur );
1005 if (i > 0) {
1006 if (*ctx->cur != ',') {
1007 report_error( ctx, "Expected `,'" );
1008 return FALSE;
1009 }
1010 ctx->cur++;
1011 eat_opt_white( &ctx->cur );
1012 }
1013 if (!parse_float( &ctx->cur, &values[i] )) {
1014 report_error( ctx, "Expected literal floating point" );
1015 return FALSE;
1016 }
1017 }
1018 eat_opt_white( &ctx->cur );
1019 if (*ctx->cur != '}') {
1020 report_error( ctx, "Expected `}'" );
1021 return FALSE;
1022 }
1023 ctx->cur++;
1024
1025 return TRUE;
1026 }
1027
1028 static boolean parse_declaration( struct translate_ctx *ctx )
1029 {
1030 struct tgsi_full_declaration decl;
1031 uint file;
1032 struct parsed_dcl_bracket brackets[2];
1033 int num_brackets;
1034 uint writemask;
1035 const char *cur;
1036 uint advance;
1037 boolean is_vs_input;
1038 boolean is_imm_array;
1039
1040 assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT);
1041 assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT);
1042
1043 if (!eat_white( &ctx->cur )) {
1044 report_error( ctx, "Syntax error" );
1045 return FALSE;
1046 }
1047 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1048 return FALSE;
1049 if (!parse_opt_writemask( ctx, &writemask ))
1050 return FALSE;
1051
1052 decl = tgsi_default_full_declaration();
1053 decl.Declaration.File = file;
1054 decl.Declaration.UsageMask = writemask;
1055
1056 if (num_brackets == 1) {
1057 decl.Range.First = brackets[0].first;
1058 decl.Range.Last = brackets[0].last;
1059 } else {
1060 decl.Range.First = brackets[1].first;
1061 decl.Range.Last = brackets[1].last;
1062
1063 decl.Declaration.Dimension = 1;
1064 decl.Dim.Index2D = brackets[0].first;
1065 }
1066
1067 is_vs_input = (file == TGSI_FILE_INPUT &&
1068 ctx->processor == TGSI_PROCESSOR_VERTEX);
1069 is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY);
1070
1071 cur = ctx->cur;
1072 eat_opt_white( &cur );
1073 if (*cur == ',' && !is_vs_input) {
1074 uint i;
1075
1076 cur++;
1077 eat_opt_white( &cur );
1078 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1079 if (str_match_no_case( &cur, semantic_names[i] )) {
1080 const char *cur2 = cur;
1081 uint index;
1082
1083 if (is_digit_alpha_underscore( cur ))
1084 continue;
1085 eat_opt_white( &cur2 );
1086 if (*cur2 == '[') {
1087 cur2++;
1088 eat_opt_white( &cur2 );
1089 if (!parse_uint( &cur2, &index )) {
1090 report_error( ctx, "Expected literal integer" );
1091 return FALSE;
1092 }
1093 eat_opt_white( &cur2 );
1094 if (*cur2 != ']') {
1095 report_error( ctx, "Expected `]'" );
1096 return FALSE;
1097 }
1098 cur2++;
1099
1100 decl.Semantic.Index = index;
1101
1102 cur = cur2;
1103 }
1104
1105 decl.Declaration.Semantic = 1;
1106 decl.Semantic.Name = i;
1107
1108 ctx->cur = cur;
1109 break;
1110 }
1111 }
1112 } else if (is_imm_array) {
1113 unsigned i;
1114 float *vals_itr;
1115 /* we have our immediate data */
1116 if (*cur != '{') {
1117 report_error( ctx, "Immediate array without data" );
1118 return FALSE;
1119 }
1120 ++cur;
1121 ctx->cur = cur;
1122
1123 decl.ImmediateData.u =
1124 MALLOC(sizeof(union tgsi_immediate_data) * 4 *
1125 (decl.Range.Last + 1));
1126 vals_itr = (float*)decl.ImmediateData.u;
1127 for (i = 0; i <= decl.Range.Last; ++i) {
1128 if (!parse_immediate_data(ctx, vals_itr)) {
1129 FREE(decl.ImmediateData.u);
1130 return FALSE;
1131 }
1132 vals_itr += 4;
1133 eat_opt_white( &ctx->cur );
1134 if (*ctx->cur != ',') {
1135 if (i != decl.Range.Last) {
1136 report_error( ctx, "Not enough data in immediate array!" );
1137 FREE(decl.ImmediateData.u);
1138 return FALSE;
1139 }
1140 } else
1141 ++ctx->cur;
1142 }
1143 eat_opt_white( &ctx->cur );
1144 if (*ctx->cur != '}') {
1145 FREE(decl.ImmediateData.u);
1146 report_error( ctx, "Immediate array data missing closing '}'" );
1147 return FALSE;
1148 }
1149 ++ctx->cur;
1150 }
1151
1152 cur = ctx->cur;
1153 eat_opt_white( &cur );
1154 if (*cur == ',' && !is_vs_input) {
1155 uint i;
1156
1157 cur++;
1158 eat_opt_white( &cur );
1159 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1160 if (str_match_no_case( &cur, interpolate_names[i] )) {
1161 if (is_digit_alpha_underscore( cur ))
1162 continue;
1163 decl.Declaration.Interpolate = i;
1164
1165 ctx->cur = cur;
1166 break;
1167 }
1168 }
1169 if (i == TGSI_INTERPOLATE_COUNT) {
1170 report_error( ctx, "Expected semantic or interpolate attribute" );
1171 return FALSE;
1172 }
1173 }
1174
1175 advance = tgsi_build_full_declaration(
1176 &decl,
1177 ctx->tokens_cur,
1178 ctx->header,
1179 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1180
1181 if (is_imm_array)
1182 FREE(decl.ImmediateData.u);
1183
1184 if (advance == 0)
1185 return FALSE;
1186 ctx->tokens_cur += advance;
1187
1188 return TRUE;
1189 }
1190
1191 static boolean parse_immediate( struct translate_ctx *ctx )
1192 {
1193 struct tgsi_full_immediate imm;
1194 float values[4];
1195 uint advance;
1196
1197 if (!eat_white( &ctx->cur )) {
1198 report_error( ctx, "Syntax error" );
1199 return FALSE;
1200 }
1201 if (!str_match_no_case( &ctx->cur, "FLT32" ) ||
1202 is_digit_alpha_underscore( ctx->cur )) {
1203 report_error( ctx, "Expected `FLT32'" );
1204 return FALSE;
1205 }
1206
1207 parse_immediate_data(ctx, values);
1208
1209 imm = tgsi_default_full_immediate();
1210 imm.Immediate.NrTokens += 4;
1211 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
1212 imm.u[0].Float = values[0];
1213 imm.u[1].Float = values[1];
1214 imm.u[2].Float = values[2];
1215 imm.u[3].Float = values[3];
1216
1217 advance = tgsi_build_full_immediate(
1218 &imm,
1219 ctx->tokens_cur,
1220 ctx->header,
1221 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1222 if (advance == 0)
1223 return FALSE;
1224 ctx->tokens_cur += advance;
1225
1226 return TRUE;
1227 }
1228
1229 static const char *property_names[] =
1230 {
1231 "GS_INPUT_PRIMITIVE",
1232 "GS_OUTPUT_PRIMITIVE",
1233 "GS_MAX_OUTPUT_VERTICES",
1234 "FS_COORD_ORIGIN",
1235 "FS_COORD_PIXEL_CENTER"
1236 };
1237
1238 static const char *primitive_names[] =
1239 {
1240 "POINTS",
1241 "LINES",
1242 "LINE_LOOP",
1243 "LINE_STRIP",
1244 "TRIANGLES",
1245 "TRIANGLE_STRIP",
1246 "TRIANGLE_FAN",
1247 "QUADS",
1248 "QUAD_STRIP",
1249 "POLYGON"
1250 };
1251
1252 static const char *fs_coord_origin_names[] =
1253 {
1254 "UPPER_LEFT",
1255 "LOWER_LEFT"
1256 };
1257
1258 static const char *fs_coord_pixel_center_names[] =
1259 {
1260 "HALF_INTEGER",
1261 "INTEGER"
1262 };
1263
1264
1265 static boolean
1266 parse_primitive( const char **pcur, uint *primitive )
1267 {
1268 uint i;
1269
1270 for (i = 0; i < PIPE_PRIM_MAX; i++) {
1271 const char *cur = *pcur;
1272
1273 if (str_match_no_case( &cur, primitive_names[i])) {
1274 *primitive = i;
1275 *pcur = cur;
1276 return TRUE;
1277 }
1278 }
1279 return FALSE;
1280 }
1281
1282 static boolean
1283 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1284 {
1285 uint i;
1286
1287 for (i = 0; i < sizeof(fs_coord_origin_names) / sizeof(fs_coord_origin_names[0]); i++) {
1288 const char *cur = *pcur;
1289
1290 if (str_match_no_case( &cur, fs_coord_origin_names[i])) {
1291 *fs_coord_origin = i;
1292 *pcur = cur;
1293 return TRUE;
1294 }
1295 }
1296 return FALSE;
1297 }
1298
1299 static boolean
1300 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1301 {
1302 uint i;
1303
1304 for (i = 0; i < sizeof(fs_coord_pixel_center_names) / sizeof(fs_coord_pixel_center_names[0]); i++) {
1305 const char *cur = *pcur;
1306
1307 if (str_match_no_case( &cur, fs_coord_pixel_center_names[i])) {
1308 *fs_coord_pixel_center = i;
1309 *pcur = cur;
1310 return TRUE;
1311 }
1312 }
1313 return FALSE;
1314 }
1315
1316
1317 static boolean parse_property( struct translate_ctx *ctx )
1318 {
1319 struct tgsi_full_property prop;
1320 uint property_name;
1321 uint values[8];
1322 uint advance;
1323 char id[64];
1324
1325 if (!eat_white( &ctx->cur )) {
1326 report_error( ctx, "Syntax error" );
1327 return FALSE;
1328 }
1329 if (!parse_identifier( &ctx->cur, id )) {
1330 report_error( ctx, "Syntax error" );
1331 return FALSE;
1332 }
1333 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1334 ++property_name) {
1335 if (streq_nocase_uprcase(property_names[property_name], id)) {
1336 break;
1337 }
1338 }
1339 if (property_name >= TGSI_PROPERTY_COUNT) {
1340 debug_printf( "\nError: Unknown property : '%s'", id );
1341 return FALSE;
1342 }
1343
1344 eat_opt_white( &ctx->cur );
1345 switch(property_name) {
1346 case TGSI_PROPERTY_GS_INPUT_PRIM:
1347 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1348 if (!parse_primitive(&ctx->cur, &values[0] )) {
1349 report_error( ctx, "Unknown primitive name as property!" );
1350 return FALSE;
1351 }
1352 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1353 ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1354 ctx->implied_array_size = u_vertices_per_prim(values[0]);
1355 }
1356 break;
1357 case TGSI_PROPERTY_FS_COORD_ORIGIN:
1358 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1359 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1360 return FALSE;
1361 }
1362 break;
1363 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1364 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1365 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1366 return FALSE;
1367 }
1368 break;
1369 default:
1370 if (!parse_uint(&ctx->cur, &values[0] )) {
1371 report_error( ctx, "Expected unsigned integer as property!" );
1372 return FALSE;
1373 }
1374 }
1375
1376 prop = tgsi_default_full_property();
1377 prop.Property.PropertyName = property_name;
1378 prop.Property.NrTokens += 1;
1379 prop.u[0].Data = values[0];
1380
1381 advance = tgsi_build_full_property(
1382 &prop,
1383 ctx->tokens_cur,
1384 ctx->header,
1385 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1386 if (advance == 0)
1387 return FALSE;
1388 ctx->tokens_cur += advance;
1389
1390 return TRUE;
1391 }
1392
1393
1394 static boolean translate( struct translate_ctx *ctx )
1395 {
1396 eat_opt_white( &ctx->cur );
1397 if (!parse_header( ctx ))
1398 return FALSE;
1399
1400 while (*ctx->cur != '\0') {
1401 uint label_val = 0;
1402 if (!eat_white( &ctx->cur )) {
1403 report_error( ctx, "Syntax error" );
1404 return FALSE;
1405 }
1406
1407 if (*ctx->cur == '\0')
1408 break;
1409 if (parse_label( ctx, &label_val )) {
1410 if (!parse_instruction( ctx, TRUE ))
1411 return FALSE;
1412 }
1413 else if (str_match_no_case( &ctx->cur, "DCL" )) {
1414 if (!parse_declaration( ctx ))
1415 return FALSE;
1416 }
1417 else if (str_match_no_case( &ctx->cur, "IMM" )) {
1418 if (!parse_immediate( ctx ))
1419 return FALSE;
1420 }
1421 else if (str_match_no_case( &ctx->cur, "PROPERTY" )) {
1422 if (!parse_property( ctx ))
1423 return FALSE;
1424 }
1425 else if (!parse_instruction( ctx, FALSE )) {
1426 return FALSE;
1427 }
1428 }
1429
1430 return TRUE;
1431 }
1432
1433 boolean
1434 tgsi_text_translate(
1435 const char *text,
1436 struct tgsi_token *tokens,
1437 uint num_tokens )
1438 {
1439 struct translate_ctx ctx;
1440
1441 ctx.text = text;
1442 ctx.cur = text;
1443 ctx.tokens = tokens;
1444 ctx.tokens_cur = tokens;
1445 ctx.tokens_end = tokens + num_tokens;
1446
1447 if (!translate( &ctx ))
1448 return FALSE;
1449
1450 return tgsi_sanity_check( tokens );
1451 }