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