dsound: Added missing LeaveCriticalSection (Coverity).
[wine] / dlls / d3dcompiler_43 / asmshader.y
1 /*
2  * Direct3D shader assembler
3  *
4  * Copyright 2008 Stefan Dösinger
5  * Copyright 2009 Matteo Bruni
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 %{
23 #include "config.h"
24 #include "wine/port.h"
25 #include "wine/debug.h"
26
27 #include "d3dcompiler_private.h"
28
29 #include <stdio.h>
30
31 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
32
33 struct asm_parser asm_ctx;
34
35 /* Error reporting function */
36 void asmparser_message(struct asm_parser *ctx, const char *fmt, ...) {
37     va_list args;
38     char* newbuffer;
39     int rc, newsize;
40
41     if(ctx->messagecapacity == 0) {
42         ctx->messages = asm_alloc(MESSAGEBUFFER_INITIAL_SIZE);
43         if(ctx->messages == NULL) {
44             ERR("Error allocating memory for parser messages\n");
45             return;
46         }
47         ctx->messagecapacity = MESSAGEBUFFER_INITIAL_SIZE;
48     }
49
50     while(1) {
51         va_start(args, fmt);
52         rc = vsnprintf(ctx->messages + ctx->messagesize,
53                        ctx->messagecapacity - ctx->messagesize, fmt, args);
54         va_end(args);
55
56         if (rc < 0 ||                                           /* C89 */
57             rc >= ctx->messagecapacity - ctx->messagesize) {    /* C99 */
58             /* Resize the buffer */
59             newsize = ctx->messagecapacity * 2;
60             newbuffer = asm_realloc(ctx->messages, newsize);
61             if(newbuffer == NULL){
62                 ERR("Error reallocating memory for parser messages\n");
63                 return;
64             }
65             ctx->messages = newbuffer;
66             ctx->messagecapacity = newsize;
67         } else {
68             ctx->messagesize += rc;
69             return;
70         }
71     }
72 }
73
74 static void asmshader_error(char const *s) {
75     asmparser_message(&asm_ctx, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no, s);
76     set_parse_status(&asm_ctx, PARSE_ERR);
77 }
78
79 static void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
80     /* We can have an additional offset without true relative addressing
81      * ex. c2[ 4 ] */
82     reg->regnum += rel->additional_offset;
83     if(!rel->has_rel_reg) {
84         reg->rel_reg = NULL;
85     } else {
86         reg->rel_reg = asm_alloc(sizeof(*reg->rel_reg));
87         if(!reg->rel_reg) {
88             return;
89         }
90         reg->rel_reg->type = rel->type;
91         reg->rel_reg->u.swizzle = rel->swizzle;
92         reg->rel_reg->regnum = rel->rel_regnum;
93     }
94 }
95
96 /* Needed lexer functions declarations */
97 int asmshader_lex(void);
98
99
100 %}
101
102 %union {
103     struct {
104         float           val;
105         BOOL            integer;
106     } immval;
107     BOOL                immbool;
108     unsigned int        regnum;
109     struct shader_reg   reg;
110     DWORD               srcmod;
111     DWORD               writemask;
112     struct {
113         DWORD           writemask;
114         DWORD           idx;
115         DWORD           last;
116     } wm_components;
117     DWORD               swizzle;
118     struct {
119         DWORD           swizzle;
120         DWORD           idx;
121     } sw_components;
122     DWORD               component;
123     struct {
124         DWORD           mod;
125         DWORD           shift;
126     } modshift;
127     BWRITER_COMPARISON_TYPE comptype;
128     struct {
129         DWORD           dclusage;
130         unsigned int    regnum;
131     } declaration;
132     BWRITERSAMPLER_TEXTURE_TYPE samplertype;
133     struct rel_reg      rel_reg;
134     struct src_regs     sregs;
135 }
136
137 /* Common instructions between vertex and pixel shaders */
138 %token INSTR_ADD
139 %token INSTR_NOP
140 %token INSTR_MOV
141 %token INSTR_SUB
142 %token INSTR_MAD
143 %token INSTR_MUL
144 %token INSTR_RCP
145 %token INSTR_RSQ
146 %token INSTR_DP3
147 %token INSTR_DP4
148 %token INSTR_MIN
149 %token INSTR_MAX
150 %token INSTR_SLT
151 %token INSTR_SGE
152 %token INSTR_ABS
153 %token INSTR_EXP
154 %token INSTR_LOG
155 %token INSTR_EXPP
156 %token INSTR_LOGP
157 %token INSTR_DST
158 %token INSTR_LRP
159 %token INSTR_FRC
160 %token INSTR_POW
161 %token INSTR_CRS
162 %token INSTR_SGN
163 %token INSTR_NRM
164 %token INSTR_SINCOS
165 %token INSTR_M4x4
166 %token INSTR_M4x3
167 %token INSTR_M3x4
168 %token INSTR_M3x3
169 %token INSTR_M3x2
170 %token INSTR_DCL
171 %token INSTR_DEF
172 %token INSTR_DEFB
173 %token INSTR_DEFI
174 %token INSTR_REP
175 %token INSTR_ENDREP
176 %token INSTR_IF
177 %token INSTR_ELSE
178 %token INSTR_ENDIF
179 %token INSTR_BREAK
180 %token INSTR_BREAKP
181 %token INSTR_CALL
182 %token INSTR_CALLNZ
183 %token INSTR_LOOP
184 %token INSTR_RET
185 %token INSTR_ENDLOOP
186 %token INSTR_LABEL
187 %token INSTR_SETP
188 %token INSTR_TEXLDL
189
190 /* Vertex shader only instructions  */
191 %token INSTR_LIT
192 %token INSTR_MOVA
193
194 /* Pixel shader only instructions   */
195 %token INSTR_CND
196 %token INSTR_CMP
197 %token INSTR_DP2ADD
198 %token INSTR_TEXCOORD
199 %token INSTR_TEXCRD
200 %token INSTR_TEXKILL
201 %token INSTR_TEX
202 %token INSTR_TEXLD
203 %token INSTR_TEXBEM
204 %token INSTR_TEXBEML
205 %token INSTR_TEXREG2AR
206 %token INSTR_TEXREG2GB
207 %token INSTR_TEXREG2RGB
208 %token INSTR_TEXM3x2PAD
209 %token INSTR_TEXM3x2TEX
210 %token INSTR_TEXM3x3PAD
211 %token INSTR_TEXM3x3SPEC
212 %token INSTR_TEXM3x3VSPEC
213 %token INSTR_TEXM3x3TEX
214 %token INSTR_TEXDP3TEX
215 %token INSTR_TEXM3x2DEPTH
216 %token INSTR_TEXDP3
217 %token INSTR_TEXM3x3
218 %token INSTR_TEXDEPTH
219 %token INSTR_BEM
220 %token INSTR_DSX
221 %token INSTR_DSY
222 %token INSTR_TEXLDP
223 %token INSTR_TEXLDB
224 %token INSTR_TEXLDD
225 %token INSTR_PHASE
226
227 /* Registers */
228 %token <regnum> REG_TEMP
229 %token <regnum> REG_OUTPUT
230 %token <regnum> REG_INPUT
231 %token <regnum> REG_CONSTFLOAT
232 %token <regnum> REG_CONSTINT
233 %token <regnum> REG_CONSTBOOL
234 %token <regnum> REG_TEXTURE
235 %token <regnum> REG_SAMPLER
236 %token <regnum> REG_TEXCRDOUT
237 %token REG_OPOS
238 %token REG_OFOG
239 %token REG_OPTS
240 %token <regnum> REG_VERTEXCOLOR
241 %token <regnum> REG_FRAGCOLOR
242 %token REG_FRAGDEPTH
243 %token REG_VPOS
244 %token REG_VFACE
245 %token REG_ADDRESS
246 %token REG_LOOP
247 %token REG_PREDICATE
248 %token <regnum> REG_LABEL
249
250 /* Version tokens */
251 %token VER_VS10
252 %token VER_VS11
253 %token VER_VS20
254 %token VER_VS2X
255 %token VER_VS30
256
257 %token VER_PS10
258 %token VER_PS11
259 %token VER_PS12
260 %token VER_PS13
261 %token VER_PS14
262 %token VER_PS20
263 %token VER_PS2X
264 %token VER_PS30
265
266 /* Output modifiers */
267 %token SHIFT_X2
268 %token SHIFT_X4
269 %token SHIFT_X8
270 %token SHIFT_D2
271 %token SHIFT_D4
272 %token SHIFT_D8
273 %token MOD_SAT
274 %token MOD_PP
275 %token MOD_CENTROID
276
277 /* Compare tokens */
278 %token COMP_GT
279 %token COMP_LT
280 %token COMP_GE
281 %token COMP_LE
282 %token COMP_EQ
283 %token COMP_NE
284
285 /* Source register modifiers */
286 %token SMOD_BIAS
287 %token SMOD_SCALEBIAS
288 %token SMOD_DZ
289 %token SMOD_DW
290 %token SMOD_ABS
291 %token SMOD_NOT
292
293 /* Sampler types */
294 %token SAMPTYPE_1D
295 %token SAMPTYPE_2D
296 %token SAMPTYPE_CUBE
297 %token SAMPTYPE_VOLUME
298
299 /* Usage declaration tokens */
300 %token <regnum> USAGE_POSITION
301 %token <regnum> USAGE_BLENDWEIGHT
302 %token <regnum> USAGE_BLENDINDICES
303 %token <regnum> USAGE_NORMAL
304 %token <regnum> USAGE_PSIZE
305 %token <regnum> USAGE_TEXCOORD
306 %token <regnum> USAGE_TANGENT
307 %token <regnum> USAGE_BINORMAL
308 %token <regnum> USAGE_TESSFACTOR
309 %token <regnum> USAGE_POSITIONT
310 %token <regnum> USAGE_COLOR
311 %token <regnum> USAGE_FOG
312 %token <regnum> USAGE_DEPTH
313 %token <regnum> USAGE_SAMPLE
314
315 /* Misc stuff */
316 %token <component> COMPONENT
317 %token <immval> IMMVAL
318 %token <immbool> IMMBOOL
319
320 %type <reg> dreg_name
321 %type <reg> dreg
322 %type <reg> sreg_name
323 %type <reg> relreg_name
324 %type <reg> sreg
325 %type <srcmod> smod
326 %type <writemask> writemask
327 %type <wm_components> wm_components
328 %type <swizzle> swizzle
329 %type <sw_components> sw_components
330 %type <modshift> omods
331 %type <modshift> omodifier
332 %type <comptype> comp
333 %type <declaration> dclusage
334 %type <reg> dcl_inputreg
335 %type <samplertype> sampdcl
336 %type <rel_reg> rel_reg
337 %type <reg> predicate
338 %type <immval> immsum
339 %type <sregs> sregs
340
341 %%
342
343 shader:               version_marker instructions
344                         {
345                             asm_ctx.funcs->end(&asm_ctx);
346                         }
347
348 version_marker:       VER_VS10
349                         {
350                             TRACE("Vertex shader 1.0\n");
351                             create_vs10_parser(&asm_ctx);
352                         }
353                     | VER_VS11
354                         {
355                             TRACE("Vertex shader 1.1\n");
356                             create_vs11_parser(&asm_ctx);
357                         }
358                     | VER_VS20
359                         {
360                             TRACE("Vertex shader 2.0\n");
361                             create_vs20_parser(&asm_ctx);
362                         }
363                     | VER_VS2X
364                         {
365                             TRACE("Vertex shader 2.x\n");
366                             create_vs2x_parser(&asm_ctx);
367                         }
368                     | VER_VS30
369                         {
370                             TRACE("Vertex shader 3.0\n");
371                             create_vs30_parser(&asm_ctx);
372                         }
373                     | VER_PS10
374                         {
375                             TRACE("Pixel  shader 1.0\n");
376                             create_ps10_parser(&asm_ctx);
377                         }
378                     | VER_PS11
379                         {
380                             TRACE("Pixel  shader 1.1\n");
381                             create_ps11_parser(&asm_ctx);
382                         }
383                     | VER_PS12
384                         {
385                             TRACE("Pixel  shader 1.2\n");
386                             create_ps12_parser(&asm_ctx);
387                         }
388                     | VER_PS13
389                         {
390                             TRACE("Pixel  shader 1.3\n");
391                             create_ps13_parser(&asm_ctx);
392                         }
393                     | VER_PS14
394                         {
395                             TRACE("Pixel  shader 1.4\n");
396                             create_ps14_parser(&asm_ctx);
397                         }
398                     | VER_PS20
399                         {
400                             TRACE("Pixel  shader 2.0\n");
401                             create_ps20_parser(&asm_ctx);
402                         }
403                     | VER_PS2X
404                         {
405                             TRACE("Pixel  shader 2.x\n");
406                             create_ps2x_parser(&asm_ctx);
407                         }
408                     | VER_PS30
409                         {
410                             TRACE("Pixel  shader 3.0\n");
411                             create_ps30_parser(&asm_ctx);
412                         }
413
414 instructions:         /* empty */
415                     | instructions complexinstr
416                             {
417                                 /* Nothing to do */
418                             }
419
420 complexinstr:         instruction
421                             {
422
423                             }
424                     | predicate instruction
425                             {
426                                 TRACE("predicate\n");
427                                 asm_ctx.funcs->predicate(&asm_ctx, &$1);
428                             }
429                     | '+' instruction
430                             {
431                                 TRACE("coissue\n");
432                                 asm_ctx.funcs->coissue(&asm_ctx);
433                             }
434
435 instruction:          INSTR_ADD omods dreg ',' sregs
436                             {
437                                 TRACE("ADD\n");
438                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ADD, $2.mod, $2.shift, 0, &$3, &$5, 2);
439                             }
440                     | INSTR_NOP
441                             {
442                                 TRACE("NOP\n");
443                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NOP, 0, 0, 0, 0, 0, 0);
444                             }
445                     | INSTR_MOV omods dreg ',' sregs
446                             {
447                                 TRACE("MOV\n");
448                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOV, $2.mod, $2.shift, 0, &$3, &$5, 1);
449                             }
450                     | INSTR_SUB omods dreg ',' sregs
451                             {
452                                 TRACE("SUB\n");
453                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SUB, $2.mod, $2.shift, 0, &$3, &$5, 2);
454                             }
455                     | INSTR_MAD omods dreg ',' sregs
456                             {
457                                 TRACE("MAD\n");
458                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAD, $2.mod, $2.shift, 0, &$3, &$5, 3);
459                             }
460                     | INSTR_MUL omods dreg ',' sregs
461                             {
462                                 TRACE("MUL\n");
463                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MUL, $2.mod, $2.shift, 0, &$3, &$5, 2);
464                             }
465                     | INSTR_RCP omods dreg ',' sregs
466                             {
467                                 TRACE("RCP\n");
468                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RCP, $2.mod, $2.shift, 0, &$3, &$5, 1);
469                             }
470                     | INSTR_RSQ omods dreg ',' sregs
471                             {
472                                 TRACE("RSQ\n");
473                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RSQ, $2.mod, $2.shift, 0, &$3, &$5, 1);
474                             }
475                     | INSTR_DP3 omods dreg ',' sregs
476                             {
477                                 TRACE("DP3\n");
478                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP3, $2.mod, $2.shift, 0, &$3, &$5, 2);
479                             }
480                     | INSTR_DP4 omods dreg ',' sregs
481                             {
482                                 TRACE("DP4\n");
483                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP4, $2.mod, $2.shift, 0, &$3, &$5, 2);
484                             }
485                     | INSTR_MIN omods dreg ',' sregs
486                             {
487                                 TRACE("MIN\n");
488                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MIN, $2.mod, $2.shift, 0, &$3, &$5, 2);
489                             }
490                     | INSTR_MAX omods dreg ',' sregs
491                             {
492                                 TRACE("MAX\n");
493                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAX, $2.mod, $2.shift, 0, &$3, &$5, 2);
494                             }
495                     | INSTR_SLT omods dreg ',' sregs
496                             {
497                                 TRACE("SLT\n");
498                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SLT, $2.mod, $2.shift, 0, &$3, &$5, 2);
499                             }
500                     | INSTR_SGE omods dreg ',' sregs
501                             {
502                                 TRACE("SGE\n");
503                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGE, $2.mod, $2.shift, 0, &$3, &$5, 2);
504                             }
505                     | INSTR_ABS omods dreg ',' sregs
506                             {
507                                 TRACE("ABS\n");
508                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ABS, $2.mod, $2.shift, 0, &$3, &$5, 1);
509                             }
510                     | INSTR_EXP omods dreg ',' sregs
511                             {
512                                 TRACE("EXP\n");
513                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXP, $2.mod, $2.shift, 0, &$3, &$5, 1);
514                             }
515                     | INSTR_LOG omods dreg ',' sregs
516                             {
517                                 TRACE("LOG\n");
518                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOG, $2.mod, $2.shift, 0, &$3, &$5, 1);
519                             }
520                     | INSTR_LOGP omods dreg ',' sregs
521                             {
522                                 TRACE("LOGP\n");
523                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOGP, $2.mod, $2.shift, 0, &$3, &$5, 1);
524                             }
525                     | INSTR_EXPP omods dreg ',' sregs
526                             {
527                                 TRACE("EXPP\n");
528                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXPP, $2.mod, $2.shift, 0, &$3, &$5, 1);
529                             }
530                     | INSTR_DST omods dreg ',' sregs
531                             {
532                                 TRACE("DST\n");
533                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DST, $2.mod, $2.shift, 0, &$3, &$5, 2);
534                             }
535                     | INSTR_LRP omods dreg ',' sregs
536                             {
537                                 TRACE("LRP\n");
538                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LRP, $2.mod, $2.shift, 0, &$3, &$5, 3);
539                             }
540                     | INSTR_FRC omods dreg ',' sregs
541                             {
542                                 TRACE("FRC\n");
543                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_FRC, $2.mod, $2.shift, 0, &$3, &$5, 1);
544                             }
545                     | INSTR_POW omods dreg ',' sregs
546                             {
547                                 TRACE("POW\n");
548                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_POW, $2.mod, $2.shift, 0, &$3, &$5, 2);
549                             }
550                     | INSTR_CRS omods dreg ',' sregs
551                             {
552                                 TRACE("CRS\n");
553                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CRS, $2.mod, $2.shift, 0, &$3, &$5, 2);
554                             }
555                     | INSTR_SGN omods dreg ',' sregs
556                             {
557                                 TRACE("SGN\n");
558                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGN, $2.mod, $2.shift, 0, &$3, &$5, 3);
559                             }
560                     | INSTR_NRM omods dreg ',' sregs
561                             {
562                                 TRACE("NRM\n");
563                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NRM, $2.mod, $2.shift, 0, &$3, &$5, 1);
564                             }
565                     | INSTR_SINCOS omods dreg ',' sregs
566                             {
567                                 TRACE("SINCOS\n");
568                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SINCOS, $2.mod, $2.shift, 0, &$3, &$5, 1);
569                             }
570                     | INSTR_M4x4 omods dreg ',' sregs
571                             {
572                                 TRACE("M4x4\n");
573                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
574                             }
575                     | INSTR_M4x3 omods dreg ',' sregs
576                             {
577                                 TRACE("M4x3\n");
578                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
579                             }
580                     | INSTR_M3x4 omods dreg ',' sregs
581                             {
582                                 TRACE("M3x4\n");
583                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
584                             }
585                     | INSTR_M3x3 omods dreg ',' sregs
586                             {
587                                 TRACE("M3x3\n");
588                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
589                             }
590                     | INSTR_M3x2 omods dreg ',' sregs
591                             {
592                                 TRACE("M3x2\n");
593                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x2, $2.mod, $2.shift, 0, &$3, &$5, 2);
594                             }
595                     | INSTR_DCL dclusage REG_OUTPUT
596                             {
597                                 struct shader_reg reg;
598                                 TRACE("Output reg declaration\n");
599                                 ZeroMemory(&reg, sizeof(reg));
600                                 reg.type = BWRITERSPR_OUTPUT;
601                                 reg.regnum = $3;
602                                 reg.rel_reg = NULL;
603                                 reg.srcmod = 0;
604                                 reg.u.writemask = BWRITERSP_WRITEMASK_ALL;
605                                 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
606                             }
607                     | INSTR_DCL dclusage REG_OUTPUT writemask
608                             {
609                                 struct shader_reg reg;
610                                 TRACE("Output reg declaration\n");
611                                 ZeroMemory(&reg, sizeof(reg));
612                                 reg.type = BWRITERSPR_OUTPUT;
613                                 reg.regnum = $3;
614                                 reg.rel_reg = NULL;
615                                 reg.srcmod = 0;
616                                 reg.u.writemask = $4;
617                                 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
618                             }
619                     | INSTR_DCL dclusage omods dcl_inputreg
620                             {
621                                 struct shader_reg reg;
622                                 TRACE("Input reg declaration\n");
623                                 if($3.shift != 0) {
624                                     asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
625                                                       asm_ctx.line_no);
626                                     set_parse_status(&asm_ctx, PARSE_ERR);
627                                 }
628                                 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) ||
629                                     asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) {
630                                     asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n",
631                                                       asm_ctx.line_no);
632                                     set_parse_status(&asm_ctx, PARSE_ERR);
633                                 }
634                                 ZeroMemory(&reg, sizeof(reg));
635                                 reg.type = $4.type;
636                                 reg.regnum = $4.regnum;
637                                 reg.rel_reg = NULL;
638                                 reg.srcmod = 0;
639                                 reg.u.writemask = BWRITERSP_WRITEMASK_ALL;
640                                 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, &reg);
641                             }
642                     | INSTR_DCL dclusage omods dcl_inputreg writemask
643                             {
644                                 struct shader_reg reg;
645                                 TRACE("Input reg declaration\n");
646                                 if($3.shift != 0) {
647                                     asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
648                                                       asm_ctx.line_no);
649                                     set_parse_status(&asm_ctx, PARSE_ERR);
650                                 }
651                                 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) ||
652                                     asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) {
653                                     asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n",
654                                                       asm_ctx.line_no);
655                                     set_parse_status(&asm_ctx, PARSE_ERR);
656                                 }
657                                 ZeroMemory(&reg, sizeof(reg));
658                                 reg.type = $4.type;
659                                 reg.regnum = $4.regnum;
660                                 reg.rel_reg = NULL;
661                                 reg.srcmod = 0;
662                                 reg.u.writemask = $5;
663                                 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, &reg);
664                             }
665                     | INSTR_DCL omods dcl_inputreg
666                             {
667                                 struct shader_reg reg;
668                                 TRACE("Input reg declaration\n");
669                                 if($2.shift != 0) {
670                                     asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
671                                                       asm_ctx.line_no);
672                                     set_parse_status(&asm_ctx, PARSE_ERR);
673                                 }
674                                 if(asm_ctx.shader->type != ST_PIXEL) {
675                                     asmparser_message(&asm_ctx, "Line %u: Declaration needs a semantic\n",
676                                                       asm_ctx.line_no);
677                                     set_parse_status(&asm_ctx, PARSE_ERR);
678                                 }
679                                 ZeroMemory(&reg, sizeof(reg));
680                                 reg.type = $3.type;
681                                 reg.regnum = $3.regnum;
682                                 reg.rel_reg = NULL;
683                                 reg.srcmod = 0;
684                                 reg.u.writemask = BWRITERSP_WRITEMASK_ALL;
685                                 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, &reg);
686                             }
687                     | INSTR_DCL omods dcl_inputreg writemask
688                             {
689                                 struct shader_reg reg;
690                                 TRACE("Input reg declaration\n");
691                                 if($2.shift != 0) {
692                                     asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
693                                                       asm_ctx.line_no);
694                                     set_parse_status(&asm_ctx, PARSE_ERR);
695                                 }
696                                 if(asm_ctx.shader->type != ST_PIXEL) {
697                                     asmparser_message(&asm_ctx, "Line %u: Declaration needs a semantic\n",
698                                                       asm_ctx.line_no);
699                                     set_parse_status(&asm_ctx, PARSE_ERR);
700                                 }
701                                 ZeroMemory(&reg, sizeof(reg));
702                                 reg.type = $3.type;
703                                 reg.regnum = $3.regnum;
704                                 reg.rel_reg = NULL;
705                                 reg.srcmod = 0;
706                                 reg.u.writemask = $4;
707                                 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, &reg);
708                             }
709                     | INSTR_DCL sampdcl omods REG_SAMPLER
710                             {
711                                 TRACE("Sampler declared\n");
712                                 if($3.shift != 0) {
713                                     asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
714                                                       asm_ctx.line_no);
715                                     set_parse_status(&asm_ctx, PARSE_ERR);
716                                 }
717                                 asm_ctx.funcs->dcl_sampler(&asm_ctx, $2, $3.mod, $4, asm_ctx.line_no);
718                             }
719                     | INSTR_DCL omods REG_SAMPLER
720                             {
721                                 TRACE("Sampler declared\n");
722                                 if($2.shift != 0) {
723                                     asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
724                                                       asm_ctx.line_no);
725                                     set_parse_status(&asm_ctx, PARSE_ERR);
726                                 }
727                                 if(asm_ctx.shader->type != ST_PIXEL) {
728                                     asmparser_message(&asm_ctx, "Line %u: Declaration needs a sampler type\n",
729                                                       asm_ctx.line_no);
730                                     set_parse_status(&asm_ctx, PARSE_ERR);
731                                 }
732                                 asm_ctx.funcs->dcl_sampler(&asm_ctx, BWRITERSTT_UNKNOWN, $2.mod, $3, asm_ctx.line_no);
733                             }
734                     | INSTR_DCL sampdcl omods dcl_inputreg
735                             {
736                                 TRACE("Error rule: sampler decl of input reg\n");
737                                 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of input regs is not valid\n",
738                                                   asm_ctx.line_no);
739                                 set_parse_status(&asm_ctx, PARSE_WARN);
740                             }
741                     | INSTR_DCL sampdcl omods REG_OUTPUT
742                             {
743                                 TRACE("Error rule: sampler decl of output reg\n");
744                                 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of output regs is not valid\n",
745                                                   asm_ctx.line_no);
746                                 set_parse_status(&asm_ctx, PARSE_WARN);
747                             }
748                     | INSTR_DEF REG_CONSTFLOAT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
749                             {
750                                 asm_ctx.funcs->constF(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val);
751                             }
752                     | INSTR_DEFI REG_CONSTINT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
753                             {
754                                 asm_ctx.funcs->constI(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val);
755                             }
756                     | INSTR_DEFB REG_CONSTBOOL ',' IMMBOOL
757                             {
758                                 asm_ctx.funcs->constB(&asm_ctx, $2, $4);
759                             }
760                     | INSTR_REP sregs
761                             {
762                                 TRACE("REP\n");
763                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_REP, 0, 0, 0, 0, &$2, 1);
764                             }
765                     | INSTR_ENDREP
766                             {
767                                 TRACE("ENDREP\n");
768                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDREP, 0, 0, 0, 0, 0, 0);
769                             }
770                     | INSTR_IF sregs
771                             {
772                                 TRACE("IF\n");
773                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IF, 0, 0, 0, 0, &$2, 1);
774                             }
775                     | INSTR_IF comp sregs
776                             {
777                                 TRACE("IFC\n");
778                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IFC, 0, 0, $2, 0, &$3, 2);
779                             }
780                     | INSTR_ELSE
781                             {
782                                 TRACE("ELSE\n");
783                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ELSE, 0, 0, 0, 0, 0, 0);
784                             }
785                     | INSTR_ENDIF
786                             {
787                                 TRACE("ENDIF\n");
788                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDIF, 0, 0, 0, 0, 0, 0);
789                             }
790                     | INSTR_BREAK
791                             {
792                                 TRACE("BREAK\n");
793                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAK, 0, 0, 0, 0, 0, 0);
794                             }
795                     | INSTR_BREAK comp sregs
796                             {
797                                 TRACE("BREAKC\n");
798                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKC, 0, 0, $2, 0, &$3, 2);
799                             }
800                     | INSTR_BREAKP sregs
801                             {
802                                 TRACE("BREAKP\n");
803                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKP, 0, 0, 0, 0, &$2, 1);
804                             }
805                     | INSTR_CALL sregs
806                             {
807                                 TRACE("CALL\n");
808                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALL, 0, 0, 0, 0, &$2, 1);
809                             }
810                     | INSTR_CALLNZ sregs
811                             {
812                                 TRACE("CALLNZ\n");
813                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALLNZ, 0, 0, 0, 0, &$2, 2);
814                             }
815                     | INSTR_LOOP sregs
816                             {
817                                 TRACE("LOOP\n");
818                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOOP, 0, 0, 0, 0, &$2, 2);
819                             }
820                     | INSTR_RET
821                             {
822                                 TRACE("RET\n");
823                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RET, 0, 0, 0, 0, 0, 0);
824                             }
825                     | INSTR_ENDLOOP
826                             {
827                                 TRACE("ENDLOOP\n");
828                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDLOOP, 0, 0, 0, 0, 0, 0);
829                             }
830                     | INSTR_LABEL sregs
831                             {
832                                 TRACE("LABEL\n");
833                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LABEL, 0, 0, 0, 0, &$2, 1);
834                             }
835                     | INSTR_SETP comp dreg ',' sregs
836                             {
837                                 TRACE("SETP\n");
838                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SETP, 0, 0, $2, &$3, &$5, 2);
839                             }
840                     | INSTR_TEXLDL omods dreg ',' sregs
841                             {
842                                 TRACE("TEXLDL\n");
843                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDL, $2.mod, $2.shift, 0, &$3, &$5, 2);
844                             }
845                     | INSTR_LIT omods dreg ',' sregs
846                             {
847                                 TRACE("LIT\n");
848                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LIT, $2.mod, $2.shift, 0, &$3, &$5, 1);
849                             }
850                     | INSTR_MOVA omods dreg ',' sregs
851                             {
852                                 TRACE("MOVA\n");
853                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOVA, $2.mod, $2.shift, 0, &$3, &$5, 1);
854                             }
855                     | INSTR_CND omods dreg ',' sregs
856                             {
857                                 TRACE("CND\n");
858                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CND, $2.mod, $2.shift, 0, &$3, &$5, 3);
859                             }
860                     | INSTR_CMP omods dreg ',' sregs
861                             {
862                                 TRACE("CMP\n");
863                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CMP, $2.mod, $2.shift, 0, &$3, &$5, 3);
864                             }
865                     | INSTR_DP2ADD omods dreg ',' sregs
866                             {
867                                 TRACE("DP2ADD\n");
868                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP2ADD, $2.mod, $2.shift, 0, &$3, &$5, 3);
869                             }
870                     | INSTR_TEXCOORD omods dreg
871                             {
872                                 TRACE("TEXCOORD\n");
873                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXCOORD, $2.mod, $2.shift, 0, &$3, 0, 0);
874                             }
875                     | INSTR_TEXCRD omods dreg ',' sregs
876                             {
877                                 TRACE("TEXCRD\n");
878                                 /* texcoord and texcrd share the same opcode */
879                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXCOORD, $2.mod, $2.shift, 0, &$3, &$5, 1);
880                             }
881                     | INSTR_TEXKILL dreg
882                             {
883                                 TRACE("TEXKILL\n");
884                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXKILL, 0, 0, 0, &$2, 0, 0);
885                             }
886                     | INSTR_TEX omods dreg
887                             {
888                                 TRACE("TEX\n");
889                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, 0, 0);
890                             }
891                     | INSTR_TEXDEPTH omods dreg
892                             {
893                                 TRACE("TEXDEPTH\n");
894                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDEPTH, $2.mod, $2.shift, 0, &$3, 0, 0);
895                             }
896                     | INSTR_TEXLD omods dreg ',' sregs
897                             {
898                                 TRACE("TEXLD\n");
899                                 /* There is more than one acceptable syntax for texld:
900                                    with 1 sreg (PS 1.4) or
901                                    with 2 sregs (PS 2.0+)
902                                    Moreover, texld shares the same opcode as the tex instruction,
903                                    so there are a total of 3 valid syntaxes
904                                    These variations are handled in asmparser.c */
905                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, &$5, 2);
906                             }
907                     | INSTR_TEXLDP omods dreg ',' sregs
908                             {
909                                 TRACE("TEXLDP\n");
910                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDP, $2.mod, $2.shift, 0, &$3, &$5, 2);
911                             }
912                     | INSTR_TEXLDB omods dreg ',' sregs
913                             {
914                                 TRACE("TEXLDB\n");
915                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDB, $2.mod, $2.shift, 0, &$3, &$5, 2);
916                             }
917                     | INSTR_TEXBEM omods dreg ',' sregs
918                             {
919                                 TRACE("TEXBEM\n");
920                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXBEM, $2.mod, $2.shift, 0, &$3, &$5, 1);
921                             }
922                     | INSTR_TEXBEML omods dreg ',' sregs
923                             {
924                                 TRACE("TEXBEML\n");
925                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXBEML, $2.mod, $2.shift, 0, &$3, &$5, 1);
926                             }
927                     | INSTR_TEXREG2AR omods dreg ',' sregs
928                             {
929                                 TRACE("TEXREG2AR\n");
930                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2AR, $2.mod, $2.shift, 0, &$3, &$5, 1);
931                             }
932                     | INSTR_TEXREG2GB omods dreg ',' sregs
933                             {
934                                 TRACE("TEXREG2GB\n");
935                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2GB, $2.mod, $2.shift, 0, &$3, &$5, 1);
936                             }
937                     | INSTR_TEXREG2RGB omods dreg ',' sregs
938                             {
939                                 TRACE("TEXREG2RGB\n");
940                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2RGB, $2.mod, $2.shift, 0, &$3, &$5, 1);
941                             }
942                     | INSTR_TEXM3x2PAD omods dreg ',' sregs
943                             {
944                                 TRACE("TEXM3x2PAD\n");
945                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2PAD, $2.mod, $2.shift, 0, &$3, &$5, 1);
946                             }
947                     | INSTR_TEXM3x3PAD omods dreg ',' sregs
948                             {
949                                 TRACE("INSTR_TEXM3x3PAD\n");
950                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3PAD, $2.mod, $2.shift, 0, &$3, &$5, 1);
951                             }
952                     | INSTR_TEXM3x3SPEC omods dreg ',' sregs
953                             {
954                                 TRACE("TEXM3x3SPEC\n");
955                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3SPEC, $2.mod, $2.shift, 0, &$3, &$5, 2);
956                             }
957                     | INSTR_TEXM3x3VSPEC omods dreg ',' sregs
958                             {
959                                 TRACE("TEXM3x3VSPEC\n");
960                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3VSPEC, $2.mod, $2.shift, 0, &$3, &$5, 1);
961                             }
962                     | INSTR_TEXM3x3TEX omods dreg ',' sregs
963                             {
964                                 TRACE("TEXM3x3TEX\n");
965                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3TEX, $2.mod, $2.shift, 0, &$3, &$5, 1);
966                             }
967                     | INSTR_TEXDP3TEX omods dreg ',' sregs
968                             {
969                                 TRACE("TEXDP3TEX\n");
970                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDP3TEX, $2.mod, $2.shift, 0, &$3, &$5, 1);
971                             }
972                     | INSTR_TEXM3x2DEPTH omods dreg ',' sregs
973                             {
974                                 TRACE("TEXM3x2DEPTH\n");
975                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2DEPTH, $2.mod, $2.shift, 0, &$3, &$5, 1);
976                             }
977                     | INSTR_TEXM3x2TEX omods dreg ',' sregs
978                             {
979                                 TRACE("TEXM3x2TEX\n");
980                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2TEX, $2.mod, $2.shift, 0, &$3, &$5, 1);
981                             }
982                     | INSTR_TEXDP3 omods dreg ',' sregs
983                             {
984                                 TRACE("TEXDP3\n");
985                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDP3, $2.mod, $2.shift, 0, &$3, &$5, 1);
986                             }
987                     | INSTR_TEXM3x3 omods dreg ',' sregs
988                             {
989                                 TRACE("TEXM3x3\n");
990                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3, $2.mod, $2.shift, 0, &$3, &$5, 1);
991                             }
992                     | INSTR_BEM omods dreg ',' sregs
993                             {
994                                 TRACE("BEM\n");
995                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BEM, $2.mod, $2.shift, 0, &$3, &$5, 2);
996                             }
997                     | INSTR_DSX omods dreg ',' sregs
998                             {
999                                 TRACE("DSX\n");
1000                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSX, $2.mod, $2.shift, 0, &$3, &$5, 1);
1001                             }
1002                     | INSTR_DSY omods dreg ',' sregs
1003                             {
1004                                 TRACE("DSY\n");
1005                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSY, $2.mod, $2.shift, 0, &$3, &$5, 1);
1006                             }
1007                     | INSTR_TEXLDD omods dreg ',' sregs
1008                             {
1009                                 TRACE("TEXLDD\n");
1010                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDD, $2.mod, $2.shift, 0, &$3, &$5, 4);
1011                             }
1012                     | INSTR_PHASE
1013                             {
1014                                 TRACE("PHASE\n");
1015                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_PHASE, 0, 0, 0, 0, 0, 0);
1016                             }
1017
1018
1019 dreg:                 dreg_name rel_reg
1020                             {
1021                                 $$.regnum = $1.regnum;
1022                                 $$.type = $1.type;
1023                                 $$.u.writemask = BWRITERSP_WRITEMASK_ALL;
1024                                 $$.srcmod = BWRITERSPSM_NONE;
1025                                 set_rel_reg(&$$, &$2);
1026                             }
1027                     | dreg_name writemask
1028                             {
1029                                 $$.regnum = $1.regnum;
1030                                 $$.type = $1.type;
1031                                 $$.u.writemask = $2;
1032                                 $$.srcmod = BWRITERSPSM_NONE;
1033                                 $$.rel_reg = NULL;
1034                             }
1035
1036 dreg_name:            REG_TEMP
1037                         {
1038                             $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
1039                         }
1040                     | REG_OUTPUT
1041                         {
1042                             $$.regnum = $1; $$.type = BWRITERSPR_OUTPUT;
1043                         }
1044                     | REG_INPUT
1045                         {
1046                             $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1047                         }
1048                     | REG_CONSTFLOAT
1049                         {
1050                             asmparser_message(&asm_ctx, "Line %u: Register c%u is not a valid destination register\n",
1051                                               asm_ctx.line_no, $1);
1052                             set_parse_status(&asm_ctx, PARSE_WARN);
1053                         }
1054                     | REG_CONSTINT
1055                         {
1056                             asmparser_message(&asm_ctx, "Line %u: Register i%u is not a valid destination register\n",
1057                                               asm_ctx.line_no, $1);
1058                             set_parse_status(&asm_ctx, PARSE_WARN);
1059                         }
1060                     | REG_CONSTBOOL
1061                         {
1062                             asmparser_message(&asm_ctx, "Line %u: Register b%u is not a valid destination register\n",
1063                                               asm_ctx.line_no, $1);
1064                             set_parse_status(&asm_ctx, PARSE_WARN);
1065                         }
1066                     | REG_TEXTURE
1067                         {
1068                             $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1069                         }
1070                     | REG_TEXCRDOUT
1071                         {
1072                             $$.regnum = $1; $$.type = BWRITERSPR_TEXCRDOUT;
1073                         }
1074                     | REG_SAMPLER
1075                         {
1076                             asmparser_message(&asm_ctx, "Line %u: Register s%u is not a valid destination register\n",
1077                                               asm_ctx.line_no, $1);
1078                             set_parse_status(&asm_ctx, PARSE_WARN);
1079                         }
1080                     | REG_OPOS
1081                         {
1082                             $$.regnum = BWRITERSRO_POSITION; $$.type = BWRITERSPR_RASTOUT;
1083                         }
1084                     | REG_OPTS
1085                         {
1086                             $$.regnum = BWRITERSRO_POINT_SIZE; $$.type = BWRITERSPR_RASTOUT;
1087                         }
1088                     | REG_OFOG
1089                         {
1090                             $$.regnum = BWRITERSRO_FOG; $$.type = BWRITERSPR_RASTOUT;
1091                         }
1092                     | REG_VERTEXCOLOR
1093                         {
1094                             $$.regnum = $1; $$.type = BWRITERSPR_ATTROUT;
1095                         }
1096                     | REG_FRAGCOLOR
1097                         {
1098                             $$.regnum = $1; $$.type = BWRITERSPR_COLOROUT;
1099                         }
1100                     | REG_FRAGDEPTH
1101                         {
1102                             $$.regnum = 0; $$.type = BWRITERSPR_DEPTHOUT;
1103                         }
1104                     | REG_PREDICATE
1105                         {
1106                             $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
1107                         }
1108                     | REG_VPOS
1109                         {
1110                             asmparser_message(&asm_ctx, "Line %u: Register vPos is not a valid destination register\n",
1111                                               asm_ctx.line_no);
1112                             set_parse_status(&asm_ctx, PARSE_WARN);
1113                         }
1114                     | REG_VFACE
1115                         {
1116                             asmparser_message(&asm_ctx, "Line %u: Register vFace is not a valid destination register\n",
1117                                               asm_ctx.line_no);
1118                             set_parse_status(&asm_ctx, PARSE_WARN);
1119                         }
1120                     | REG_ADDRESS
1121                         {
1122                             /* index 0 is hardcoded for the addr register */
1123                             $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1124                         }
1125                     | REG_LOOP
1126                         {
1127                             asmparser_message(&asm_ctx, "Line %u: Register aL is not a valid destination register\n",
1128                                               asm_ctx.line_no);
1129                             set_parse_status(&asm_ctx, PARSE_WARN);
1130                         }
1131
1132 writemask:            '.' wm_components
1133                         {
1134                             if($2.writemask == SWIZZLE_ERR) {
1135                                 asmparser_message(&asm_ctx, "Line %u: Invalid writemask specified\n",
1136                                                   asm_ctx.line_no);
1137                                 set_parse_status(&asm_ctx, PARSE_ERR);
1138                                 /* Provide a correct writemask to prevent following complaints */
1139                                 $$ = BWRITERSP_WRITEMASK_ALL;
1140                             }
1141                             else {
1142                                 $$ = $2.writemask;
1143                                 TRACE("Writemask: %x\n", $$);
1144                             }
1145                         }
1146
1147 wm_components:        COMPONENT
1148                         {
1149                             $$.writemask = 1 << $1;
1150                             $$.last = $1;
1151                             $$.idx = 1;
1152                         }
1153                     | wm_components COMPONENT
1154                         {
1155                             if($1.writemask == SWIZZLE_ERR || $1.idx == 4)
1156                                 /* Wrong writemask */
1157                                 $$.writemask = SWIZZLE_ERR;
1158                             else {
1159                                 if($2 <= $1.last)
1160                                     $$.writemask = SWIZZLE_ERR;
1161                                 else {
1162                                     $$.writemask = $1.writemask | (1 << $2);
1163                                     $$.idx = $1.idx + 1;
1164                                 }
1165                             }
1166                         }
1167
1168 swizzle:              /* empty */
1169                         {
1170                             $$ = BWRITERVS_NOSWIZZLE;
1171                             TRACE("Default swizzle: %08x\n", $$);
1172                         }
1173                     | '.' sw_components
1174                         {
1175                             if($2.swizzle == SWIZZLE_ERR) {
1176                                 asmparser_message(&asm_ctx, "Line %u: Invalid swizzle\n",
1177                                                   asm_ctx.line_no);
1178                                 set_parse_status(&asm_ctx, PARSE_ERR);
1179                                 /* Provide a correct swizzle to prevent following complaints */
1180                                 $$ = BWRITERVS_NOSWIZZLE;
1181                             }
1182                             else {
1183                                 DWORD last, i;
1184
1185                                 $$ = $2.swizzle << BWRITERVS_SWIZZLE_SHIFT;
1186                                 /* Fill the swizzle by extending the last component */
1187                                 last = ($2.swizzle >> 2 * ($2.idx - 1)) & 0x03;
1188                                 for(i = $2.idx; i < 4; i++){
1189                                     $$ |= last << (BWRITERVS_SWIZZLE_SHIFT + 2 * i);
1190                                 }
1191                                 TRACE("Got a swizzle: %08x\n", $$);
1192                             }
1193                         }
1194
1195 sw_components:        COMPONENT
1196                         {
1197                             $$.swizzle = $1;
1198                             $$.idx = 1;
1199                         }
1200                     | sw_components COMPONENT
1201                         {
1202                             if($1.idx == 4) {
1203                                 /* Too many sw_components */
1204                                 $$.swizzle = SWIZZLE_ERR;
1205                                 $$.idx = 4;
1206                             }
1207                             else {
1208                                 $$.swizzle = $1.swizzle | ($2 << 2 * $1.idx);
1209                                 $$.idx = $1.idx + 1;
1210                             }
1211                         }
1212
1213 omods:                 /* Empty */
1214                         {
1215                             $$.mod = 0;
1216                             $$.shift = 0;
1217                         }
1218                     | omods omodifier
1219                         {
1220                             $$.mod = $1.mod | $2.mod;
1221                             if($1.shift && $2.shift) {
1222                                 asmparser_message(&asm_ctx, "Line %u: More than one shift flag\n",
1223                                                   asm_ctx.line_no);
1224                                 set_parse_status(&asm_ctx, PARSE_ERR);
1225                                 $$.shift = $1.shift;
1226                             } else {
1227                                 $$.shift = $1.shift | $2.shift;
1228                             }
1229                         }
1230
1231 omodifier:            SHIFT_X2
1232                         {
1233                             $$.mod = 0;
1234                             $$.shift = 1;
1235                         }
1236                     | SHIFT_X4
1237                         {
1238                             $$.mod = 0;
1239                             $$.shift = 2;
1240                         }
1241                     | SHIFT_X8
1242                         {
1243                             $$.mod = 0;
1244                             $$.shift = 3;
1245                         }
1246                     | SHIFT_D2
1247                         {
1248                             $$.mod = 0;
1249                             $$.shift = 15;
1250                         }
1251                     | SHIFT_D4
1252                         {
1253                             $$.mod = 0;
1254                             $$.shift = 14;
1255                         }
1256                     | SHIFT_D8
1257                         {
1258                             $$.mod = 0;
1259                             $$.shift = 13;
1260                         }
1261                     | MOD_SAT
1262                         {
1263                             $$.mod = BWRITERSPDM_SATURATE;
1264                             $$.shift = 0;
1265                         }
1266                     | MOD_PP
1267                         {
1268                             $$.mod = BWRITERSPDM_PARTIALPRECISION;
1269                             $$.shift = 0;
1270                         }
1271                     | MOD_CENTROID
1272                         {
1273                             $$.mod = BWRITERSPDM_MSAMPCENTROID;
1274                             $$.shift = 0;
1275                         }
1276
1277 sregs:                sreg
1278                         {
1279                             $$.reg[0] = $1;
1280                             $$.count = 1;
1281                         }
1282                     | sregs ',' sreg
1283                         {
1284                             if($$.count == MAX_SRC_REGS){
1285                                 asmparser_message(&asm_ctx, "Line %u: Too many source registers in this instruction\n",
1286                                                   asm_ctx.line_no);
1287                                 set_parse_status(&asm_ctx, PARSE_ERR);
1288                             }
1289                             else
1290                                 $$.reg[$$.count++] = $3;
1291                         }
1292
1293 sreg:                   sreg_name rel_reg swizzle
1294                         {
1295                             $$.type = $1.type;
1296                             $$.regnum = $1.regnum;
1297                             $$.u.swizzle = $3;
1298                             $$.srcmod = BWRITERSPSM_NONE;
1299                             set_rel_reg(&$$, &$2);
1300                         }
1301                     | sreg_name rel_reg smod swizzle
1302                         {
1303                             $$.type = $1.type;
1304                             $$.regnum = $1.regnum;
1305                             set_rel_reg(&$$, &$2);
1306                             $$.srcmod = $3;
1307                             $$.u.swizzle = $4;
1308                         }
1309                     | '-' sreg_name rel_reg swizzle
1310                         {
1311                             $$.type = $2.type;
1312                             $$.regnum = $2.regnum;
1313                             $$.srcmod = BWRITERSPSM_NEG;
1314                             set_rel_reg(&$$, &$3);
1315                             $$.u.swizzle = $4;
1316                         }
1317                     | '-' sreg_name rel_reg smod swizzle
1318                         {
1319                             $$.type = $2.type;
1320                             $$.regnum = $2.regnum;
1321                             set_rel_reg(&$$, &$3);
1322                             switch($4) {
1323                                 case BWRITERSPSM_BIAS: $$.srcmod = BWRITERSPSM_BIASNEG; break;
1324                                 case BWRITERSPSM_X2:   $$.srcmod = BWRITERSPSM_X2NEG;   break;
1325                                 case BWRITERSPSM_SIGN: $$.srcmod = BWRITERSPSM_SIGNNEG; break;
1326                                 case BWRITERSPSM_ABS:  $$.srcmod = BWRITERSPSM_ABSNEG;  break;
1327                                 case BWRITERSPSM_DZ:
1328                                     asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DZ\n",
1329                                                       asm_ctx.line_no);
1330                                     set_parse_status(&asm_ctx, PARSE_ERR);
1331                                     break;
1332                                 case BWRITERSPSM_DW:
1333                                     asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DW\n",
1334                                                       asm_ctx.line_no);
1335                                     set_parse_status(&asm_ctx, PARSE_ERR);
1336                                     break;
1337                                 default:
1338                                     FIXME("Unhandled combination of NEGATE and %u\n", $4);
1339                             }
1340                             $$.u.swizzle = $5;
1341                         }
1342                     | IMMVAL '-' sreg_name rel_reg swizzle
1343                         {
1344                             if($1.val != 1.0 || (!$1.integer)) {
1345                                 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP, "
1346                                                   "%g - reg found\n", asm_ctx.line_no, $1.val);
1347                                 set_parse_status(&asm_ctx, PARSE_ERR);
1348                             }
1349                             /* Complement - not compatible with other source modifiers */
1350                             $$.type = $3.type;
1351                             $$.regnum = $3.regnum;
1352                             $$.srcmod = BWRITERSPSM_COMP;
1353                             set_rel_reg(&$$, &$4);
1354                             $$.u.swizzle = $5;
1355                         }
1356                     | IMMVAL '-' sreg_name rel_reg smod swizzle
1357                         {
1358                             /* For nicer error reporting */
1359                             if($1.val != 1.0 || (!$1.integer)) {
1360                                 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP\n",
1361                                                   asm_ctx.line_no);
1362                                 set_parse_status(&asm_ctx, PARSE_ERR);
1363                             } else {
1364                                 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: D3DSPSM_COMP and %s\n",
1365                                                   asm_ctx.line_no,
1366                                                   debug_print_srcmod($5));
1367                                 set_parse_status(&asm_ctx, PARSE_ERR);
1368                             }
1369                         }
1370                     | SMOD_NOT sreg_name swizzle
1371                         {
1372                             $$.type = $2.type;
1373                             $$.regnum = $2.regnum;
1374                             $$.rel_reg = NULL;
1375                             $$.srcmod = BWRITERSPSM_NOT;
1376                             $$.u.swizzle = $3;
1377                         }
1378
1379 rel_reg:               /* empty */
1380                         {
1381                             $$.has_rel_reg = FALSE;
1382                             $$.additional_offset = 0;
1383                         }
1384                     | '[' immsum ']'
1385                         {
1386                             $$.has_rel_reg = FALSE;
1387                             $$.additional_offset = $2.val;
1388                         }
1389                     | '[' relreg_name swizzle ']'
1390                         {
1391                             $$.has_rel_reg = TRUE;
1392                             $$.type = $2.type;
1393                             $$.additional_offset = 0;
1394                             $$.rel_regnum = $2.regnum;
1395                             $$.swizzle = $3;
1396                         }
1397                     | '[' immsum '+' relreg_name swizzle ']'
1398                         {
1399                             $$.has_rel_reg = TRUE;
1400                             $$.type = $4.type;
1401                             $$.additional_offset = $2.val;
1402                             $$.rel_regnum = $4.regnum;
1403                             $$.swizzle = $5;
1404                         }
1405                     | '[' relreg_name swizzle '+' immsum ']'
1406                         {
1407                             $$.has_rel_reg = TRUE;
1408                             $$.type = $2.type;
1409                             $$.additional_offset = $5.val;
1410                             $$.rel_regnum = $2.regnum;
1411                             $$.swizzle = $3;
1412                         }
1413                     | '[' immsum '+' relreg_name swizzle '+' immsum ']'
1414                         {
1415                             $$.has_rel_reg = TRUE;
1416                             $$.type = $4.type;
1417                             $$.additional_offset = $2.val + $7.val;
1418                             $$.rel_regnum = $4.regnum;
1419                             $$.swizzle = $5;
1420                         }
1421
1422 immsum:               IMMVAL
1423                         {
1424                             if(!$1.integer) {
1425                                 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1426                                                   asm_ctx.line_no, $1.val);
1427                                 set_parse_status(&asm_ctx, PARSE_ERR);
1428                             }
1429                             $$.val = $1.val;
1430                         }
1431                     | immsum '+' IMMVAL
1432                         {
1433                             if(!$3.integer) {
1434                                 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1435                                                   asm_ctx.line_no, $3.val);
1436                                 set_parse_status(&asm_ctx, PARSE_ERR);
1437                             }
1438                             $$.val = $1.val + $3.val;
1439                         }
1440
1441 smod:                 SMOD_BIAS
1442                         {
1443                             $$ = BWRITERSPSM_BIAS;
1444                         }
1445                     | SHIFT_X2
1446                         {
1447                             $$ = BWRITERSPSM_X2;
1448                         }
1449                     | SMOD_SCALEBIAS
1450                         {
1451                             $$ = BWRITERSPSM_SIGN;
1452                         }
1453                     | SMOD_DZ
1454                         {
1455                             $$ = BWRITERSPSM_DZ;
1456                         }
1457                     | SMOD_DW
1458                         {
1459                             $$ = BWRITERSPSM_DW;
1460                         }
1461                     | SMOD_ABS
1462                         {
1463                             $$ = BWRITERSPSM_ABS;
1464                         }
1465
1466 relreg_name:          REG_ADDRESS
1467                         {
1468                             $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1469                         }
1470                     | REG_LOOP
1471                         {
1472                             $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1473                         }
1474
1475 sreg_name:            REG_TEMP
1476                         {
1477                             $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
1478                         }
1479                     | REG_OUTPUT
1480                         {
1481                             asmparser_message(&asm_ctx, "Line %u: Register o%u is not a valid source register\n",
1482                                               asm_ctx.line_no, $1);
1483                             set_parse_status(&asm_ctx, PARSE_WARN);
1484                         }
1485                     | REG_INPUT
1486                         {
1487                             $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1488                         }
1489                     | REG_CONSTFLOAT
1490                         {
1491                             $$.regnum = $1; $$.type = BWRITERSPR_CONST;
1492                         }
1493                     | REG_CONSTINT
1494                         {
1495                             $$.regnum = $1; $$.type = BWRITERSPR_CONSTINT;
1496                         }
1497                     | REG_CONSTBOOL
1498                         {
1499                             $$.regnum = $1; $$.type = BWRITERSPR_CONSTBOOL;
1500                         }
1501                     | REG_TEXTURE
1502                         {
1503                             $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1504                         }
1505                     | REG_TEXCRDOUT
1506                         {
1507                             asmparser_message(&asm_ctx, "Line %u: Register oT%u is not a valid source register\n",
1508                                               asm_ctx.line_no, $1);
1509                             set_parse_status(&asm_ctx, PARSE_WARN);
1510                         }
1511                     | REG_SAMPLER
1512                         {
1513                             $$.regnum = $1; $$.type = BWRITERSPR_SAMPLER;
1514                         }
1515                     | REG_OPOS
1516                         {
1517                             asmparser_message(&asm_ctx, "Line %u: Register oPos is not a valid source register\n",
1518                                               asm_ctx.line_no);
1519                             set_parse_status(&asm_ctx, PARSE_WARN);
1520                         }
1521                     | REG_OFOG
1522                         {
1523                             asmparser_message(&asm_ctx, "Line %u: Register oFog is not a valid source register\n",
1524                                               asm_ctx.line_no);
1525                             set_parse_status(&asm_ctx, PARSE_WARN);
1526                         }
1527                     | REG_VERTEXCOLOR
1528                         {
1529                             asmparser_message(&asm_ctx, "Line %u: Register oD%u is not a valid source register\n",
1530                                               asm_ctx.line_no, $1);
1531                             set_parse_status(&asm_ctx, PARSE_WARN);
1532                         }
1533                     | REG_FRAGCOLOR
1534                         {
1535                             asmparser_message(&asm_ctx, "Line %u: Register oC%u is not a valid source register\n",
1536                                               asm_ctx.line_no, $1);
1537                             set_parse_status(&asm_ctx, PARSE_WARN);
1538                         }
1539                     | REG_FRAGDEPTH
1540                         {
1541                             asmparser_message(&asm_ctx, "Line %u: Register oDepth is not a valid source register\n",
1542                                               asm_ctx.line_no);
1543                             set_parse_status(&asm_ctx, PARSE_WARN);
1544                         }
1545                     | REG_PREDICATE
1546                         {
1547                             $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
1548                         }
1549                     | REG_VPOS
1550                         {
1551                             $$.regnum = 0; $$.type = BWRITERSPR_MISCTYPE;
1552                         }
1553                     | REG_VFACE
1554                         {
1555                             $$.regnum = 1; $$.type = BWRITERSPR_MISCTYPE;
1556                         }
1557                     | REG_ADDRESS
1558                         {
1559                             $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1560                         }
1561                     | REG_LOOP
1562                         {
1563                             $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1564                         }
1565                     | REG_LABEL
1566                         {
1567                             $$.regnum = $1; $$.type = BWRITERSPR_LABEL;
1568                         }
1569
1570 comp:                 COMP_GT           { $$ = BWRITER_COMPARISON_GT;       }
1571                     | COMP_LT           { $$ = BWRITER_COMPARISON_LT;       }
1572                     | COMP_GE           { $$ = BWRITER_COMPARISON_GE;       }
1573                     | COMP_LE           { $$ = BWRITER_COMPARISON_LE;       }
1574                     | COMP_EQ           { $$ = BWRITER_COMPARISON_EQ;       }
1575                     | COMP_NE           { $$ = BWRITER_COMPARISON_NE;       }
1576
1577 dclusage:             USAGE_POSITION
1578                         {
1579                             TRACE("dcl_position%u\n", $1);
1580                             $$.regnum = $1;
1581                             $$.dclusage = BWRITERDECLUSAGE_POSITION;
1582                         }
1583                     | USAGE_BLENDWEIGHT
1584                         {
1585                             TRACE("dcl_blendweight%u\n", $1);
1586                             $$.regnum = $1;
1587                             $$.dclusage = BWRITERDECLUSAGE_BLENDWEIGHT;
1588                         }
1589                     | USAGE_BLENDINDICES
1590                         {
1591                             TRACE("dcl_blendindices%u\n", $1);
1592                             $$.regnum = $1;
1593                             $$.dclusage = BWRITERDECLUSAGE_BLENDINDICES;
1594                         }
1595                     | USAGE_NORMAL
1596                         {
1597                             TRACE("dcl_normal%u\n", $1);
1598                             $$.regnum = $1;
1599                             $$.dclusage = BWRITERDECLUSAGE_NORMAL;
1600                         }
1601                     | USAGE_PSIZE
1602                         {
1603                             TRACE("dcl_psize%u\n", $1);
1604                             $$.regnum = $1;
1605                             $$.dclusage = BWRITERDECLUSAGE_PSIZE;
1606                         }
1607                     | USAGE_TEXCOORD
1608                         {
1609                             TRACE("dcl_texcoord%u\n", $1);
1610                             $$.regnum = $1;
1611                             $$.dclusage = BWRITERDECLUSAGE_TEXCOORD;
1612                         }
1613                     | USAGE_TANGENT
1614                         {
1615                             TRACE("dcl_tangent%u\n", $1);
1616                             $$.regnum = $1;
1617                             $$.dclusage = BWRITERDECLUSAGE_TANGENT;
1618                         }
1619                     | USAGE_BINORMAL
1620                         {
1621                             TRACE("dcl_binormal%u\n", $1);
1622                             $$.regnum = $1;
1623                             $$.dclusage = BWRITERDECLUSAGE_BINORMAL;
1624                         }
1625                     | USAGE_TESSFACTOR
1626                         {
1627                             TRACE("dcl_tessfactor%u\n", $1);
1628                             $$.regnum = $1;
1629                             $$.dclusage = BWRITERDECLUSAGE_TESSFACTOR;
1630                         }
1631                     | USAGE_POSITIONT
1632                         {
1633                             TRACE("dcl_positiont%u\n", $1);
1634                             $$.regnum = $1;
1635                             $$.dclusage = BWRITERDECLUSAGE_POSITIONT;
1636                         }
1637                     | USAGE_COLOR
1638                         {
1639                             TRACE("dcl_color%u\n", $1);
1640                             $$.regnum = $1;
1641                             $$.dclusage = BWRITERDECLUSAGE_COLOR;
1642                         }
1643                     | USAGE_FOG
1644                         {
1645                             TRACE("dcl_fog%u\n", $1);
1646                             $$.regnum = $1;
1647                             $$.dclusage = BWRITERDECLUSAGE_FOG;
1648                         }
1649                     | USAGE_DEPTH
1650                         {
1651                             TRACE("dcl_depth%u\n", $1);
1652                             $$.regnum = $1;
1653                             $$.dclusage = BWRITERDECLUSAGE_DEPTH;
1654                         }
1655                     | USAGE_SAMPLE
1656                         {
1657                             TRACE("dcl_sample%u\n", $1);
1658                             $$.regnum = $1;
1659                             $$.dclusage = BWRITERDECLUSAGE_SAMPLE;
1660                         }
1661
1662 dcl_inputreg:         REG_INPUT
1663                         {
1664                             $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1665                         }
1666                     | REG_TEXTURE
1667                         {
1668                             $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1669                         }
1670
1671 sampdcl:              SAMPTYPE_1D
1672                         {
1673                             $$ = BWRITERSTT_1D;
1674                         }
1675                     | SAMPTYPE_2D
1676                         {
1677                             $$ = BWRITERSTT_2D;
1678                         }
1679                     | SAMPTYPE_CUBE
1680                         {
1681                             $$ = BWRITERSTT_CUBE;
1682                         }
1683                     | SAMPTYPE_VOLUME
1684                         {
1685                             $$ = BWRITERSTT_VOLUME;
1686                         }
1687
1688 predicate:            '(' REG_PREDICATE swizzle ')'
1689                         {
1690                             $$.type = BWRITERSPR_PREDICATE;
1691                             $$.regnum = 0;
1692                             $$.rel_reg = NULL;
1693                             $$.srcmod = BWRITERSPSM_NONE;
1694                             $$.u.swizzle = $3;
1695                         }
1696                     | '(' SMOD_NOT REG_PREDICATE swizzle ')'
1697                         {
1698                             $$.type = BWRITERSPR_PREDICATE;
1699                             $$.regnum = 0;
1700                             $$.rel_reg = NULL;
1701                             $$.srcmod = BWRITERSPSM_NOT;
1702                             $$.u.swizzle = $4;
1703                         }
1704
1705 %%
1706
1707 /* New status is the worst between current status and parameter value */
1708 void set_parse_status(struct asm_parser *ctx, enum parse_status status) {
1709     if(status == PARSE_ERR) ctx->status = PARSE_ERR;
1710     else if(status == PARSE_WARN && ctx->status == PARSE_SUCCESS) ctx->status = PARSE_WARN;
1711 }
1712
1713 struct bwriter_shader *parse_asm_shader(char **messages) {
1714     struct bwriter_shader *ret = NULL;
1715
1716     asm_ctx.shader = NULL;
1717     asm_ctx.status = PARSE_SUCCESS;
1718     asm_ctx.messagesize = asm_ctx.messagecapacity = 0;
1719     asm_ctx.line_no = 1;
1720
1721     asmshader_parse();
1722
1723     if(asm_ctx.status != PARSE_ERR) ret = asm_ctx.shader;
1724     else if(asm_ctx.shader) SlDeleteShader(asm_ctx.shader);
1725
1726     if(messages) {
1727         if(asm_ctx.messagesize) {
1728             /* Shrink the buffer to the used size */
1729             *messages = asm_realloc(asm_ctx.messages, asm_ctx.messagesize + 1);
1730             if(!*messages) {
1731                 ERR("Out of memory, no messages reported\n");
1732                 asm_free(asm_ctx.messages);
1733             }
1734         } else {
1735             *messages = NULL;
1736         }
1737     } else {
1738         if(asm_ctx.messagecapacity) asm_free(asm_ctx.messages);
1739     }
1740
1741     return ret;
1742 }