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