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