comctl32/treeview: Fix possible crash in TVS_SINGELEXPAND helper (Coverity).
[wine/wine-gecko.git] / dlls / d3dx9_36 / asmshader.y
blobd1a05db9089b884eb42a0bffb61a6e97e115780b
1 /*
2 * Direct3D shader assembler
4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2009 Matteo Bruni
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.
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.
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
23 #include "config.h"
24 #include "wine/port.h"
25 #include "wine/debug.h"
27 #include "d3dx9_36_private.h"
29 #include <stdio.h>
31 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
33 struct asm_parser asm_ctx;
35 /* Needed lexer functions declarations */
36 void asmshader_error(const char *s);
37 int asmshader_lex(void);
39 void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
40 /* We can have an additional offset without true relative addressing
41 * ex. c2[ 4 ] */
42 reg->regnum += rel->additional_offset;
43 if(!rel->has_rel_reg) {
44 reg->rel_reg = NULL;
45 } else {
46 reg->rel_reg = asm_alloc(sizeof(*reg->rel_reg));
47 if(!reg->rel_reg) {
48 return;
50 reg->rel_reg->type = rel->type;
51 reg->rel_reg->swizzle = rel->swizzle;
52 reg->rel_reg->regnum = rel->rel_regnum;
58 %union {
59 struct {
60 float val;
61 BOOL integer;
62 } immval;
63 BOOL immbool;
64 unsigned int regnum;
65 struct shader_reg reg;
66 DWORD srcmod;
67 DWORD writemask;
68 struct {
69 DWORD writemask;
70 DWORD idx;
71 DWORD last;
72 } wm_components;
73 DWORD swizzle;
74 struct {
75 DWORD swizzle;
76 DWORD idx;
77 } sw_components;
78 DWORD component;
79 struct {
80 DWORD mod;
81 DWORD shift;
82 } modshift;
83 BWRITER_COMPARISON_TYPE comptype;
84 struct {
85 DWORD dclusage;
86 unsigned int regnum;
87 } declaration;
88 BWRITERSAMPLER_TEXTURE_TYPE samplertype;
89 struct rel_reg rel_reg;
90 struct src_regs sregs;
93 /* Common instructions between vertex and pixel shaders */
94 %token INSTR_ADD
95 %token INSTR_NOP
96 %token INSTR_MOV
97 %token INSTR_SUB
98 %token INSTR_MAD
99 %token INSTR_MUL
100 %token INSTR_RCP
101 %token INSTR_RSQ
102 %token INSTR_DP3
103 %token INSTR_DP4
104 %token INSTR_MIN
105 %token INSTR_MAX
106 %token INSTR_SLT
107 %token INSTR_SGE
108 %token INSTR_ABS
109 %token INSTR_EXP
110 %token INSTR_LOG
111 %token INSTR_EXPP
112 %token INSTR_LOGP
113 %token INSTR_DST
114 %token INSTR_LRP
115 %token INSTR_FRC
116 %token INSTR_POW
117 %token INSTR_CRS
118 %token INSTR_SGN
119 %token INSTR_NRM
120 %token INSTR_SINCOS
121 %token INSTR_M4x4
122 %token INSTR_M4x3
123 %token INSTR_M3x4
124 %token INSTR_M3x3
125 %token INSTR_M3x2
126 %token INSTR_DCL
127 %token INSTR_DEF
128 %token INSTR_DEFB
129 %token INSTR_DEFI
130 %token INSTR_REP
131 %token INSTR_ENDREP
132 %token INSTR_IF
133 %token INSTR_ELSE
134 %token INSTR_ENDIF
135 %token INSTR_BREAK
136 %token INSTR_BREAKP
137 %token INSTR_CALL
138 %token INSTR_CALLNZ
139 %token INSTR_LOOP
140 %token INSTR_RET
141 %token INSTR_ENDLOOP
142 %token INSTR_LABEL
143 %token INSTR_SETP
144 %token INSTR_TEXLDL
146 /* Vertex shader only instructions */
147 %token INSTR_LIT
148 %token INSTR_MOVA
150 /* Pixel shader only instructions */
151 %token INSTR_CND
152 %token INSTR_CMP
153 %token INSTR_DP2ADD
154 %token INSTR_TEXCOORD
155 %token INSTR_TEXCRD
156 %token INSTR_TEXKILL
157 %token INSTR_TEX
158 %token INSTR_TEXLD
159 %token INSTR_TEXBEM
160 %token INSTR_TEXBEML
161 %token INSTR_TEXREG2AR
162 %token INSTR_TEXREG2GB
163 %token INSTR_TEXREG2RGB
164 %token INSTR_TEXM3x2PAD
165 %token INSTR_TEXM3x2TEX
166 %token INSTR_TEXM3x3PAD
167 %token INSTR_TEXM3x3SPEC
168 %token INSTR_TEXM3x3VSPEC
169 %token INSTR_TEXM3x3TEX
170 %token INSTR_TEXDP3TEX
171 %token INSTR_TEXM3x2DEPTH
172 %token INSTR_TEXDP3
173 %token INSTR_TEXM3x3
174 %token INSTR_TEXDEPTH
175 %token INSTR_BEM
176 %token INSTR_DSX
177 %token INSTR_DSY
178 %token INSTR_TEXLDP
179 %token INSTR_TEXLDB
180 %token INSTR_TEXLDD
181 %token INSTR_PHASE
183 /* Registers */
184 %token <regnum> REG_TEMP
185 %token <regnum> REG_OUTPUT
186 %token <regnum> REG_INPUT
187 %token <regnum> REG_CONSTFLOAT
188 %token <regnum> REG_CONSTINT
189 %token <regnum> REG_CONSTBOOL
190 %token <regnum> REG_TEXTURE
191 %token <regnum> REG_SAMPLER
192 %token <regnum> REG_TEXCRDOUT
193 %token REG_OPOS
194 %token REG_OFOG
195 %token REG_OPTS
196 %token <regnum> REG_VERTEXCOLOR
197 %token <regnum> REG_FRAGCOLOR
198 %token REG_FRAGDEPTH
199 %token REG_VPOS
200 %token REG_VFACE
201 %token REG_ADDRESS
202 %token REG_LOOP
203 %token REG_PREDICATE
204 %token <regnum> REG_LABEL
206 /* Version tokens */
207 %token VER_VS10
208 %token VER_VS11
209 %token VER_VS20
210 %token VER_VS2X
211 %token VER_VS30
213 %token VER_PS10
214 %token VER_PS11
215 %token VER_PS12
216 %token VER_PS13
217 %token VER_PS14
218 %token VER_PS20
219 %token VER_PS2X
220 %token VER_PS30
222 /* Output modifiers */
223 %token SHIFT_X2
224 %token SHIFT_X4
225 %token SHIFT_X8
226 %token SHIFT_D2
227 %token SHIFT_D4
228 %token SHIFT_D8
229 %token MOD_SAT
230 %token MOD_PP
231 %token MOD_CENTROID
233 /* Compare tokens */
234 %token COMP_GT
235 %token COMP_LT
236 %token COMP_GE
237 %token COMP_LE
238 %token COMP_EQ
239 %token COMP_NE
241 /* Source register modifiers */
242 %token SMOD_BIAS
243 %token SMOD_SCALEBIAS
244 %token SMOD_DZ
245 %token SMOD_DW
246 %token SMOD_ABS
247 %token SMOD_NOT
249 /* Sampler types */
250 %token SAMPTYPE_1D
251 %token SAMPTYPE_2D
252 %token SAMPTYPE_CUBE
253 %token SAMPTYPE_VOLUME
255 /* Usage declaration tokens */
256 %token <regnum> USAGE_POSITION
257 %token <regnum> USAGE_BLENDWEIGHT
258 %token <regnum> USAGE_BLENDINDICES
259 %token <regnum> USAGE_NORMAL
260 %token <regnum> USAGE_PSIZE
261 %token <regnum> USAGE_TEXCOORD
262 %token <regnum> USAGE_TANGENT
263 %token <regnum> USAGE_BINORMAL
264 %token <regnum> USAGE_TESSFACTOR
265 %token <regnum> USAGE_POSITIONT
266 %token <regnum> USAGE_COLOR
267 %token <regnum> USAGE_FOG
268 %token <regnum> USAGE_DEPTH
269 %token <regnum> USAGE_SAMPLE
271 /* Misc stuff */
272 %token <component> COMPONENT
273 %token <immval> IMMVAL
274 %token <immbool> IMMBOOL
276 %type <reg> dreg_name
277 %type <reg> dreg
278 %type <reg> sreg_name
279 %type <reg> relreg_name
280 %type <reg> sreg
281 %type <srcmod> smod
282 %type <writemask> writemask
283 %type <wm_components> wm_components
284 %type <swizzle> swizzle
285 %type <sw_components> sw_components
286 %type <modshift> omods
287 %type <modshift> omodifier
288 %type <comptype> comp
289 %type <declaration> dclusage
290 %type <reg> dcl_inputreg
291 %type <samplertype> sampdcl
292 %type <rel_reg> rel_reg
293 %type <reg> predicate
294 %type <immval> immsum
295 %type <sregs> sregs
299 shader: version_marker instructions
301 asm_ctx.funcs->end(&asm_ctx);
304 version_marker: VER_VS10
306 TRACE("Vertex shader 1.0\n");
307 create_vs10_parser(&asm_ctx);
309 | VER_VS11
311 TRACE("Vertex shader 1.1\n");
312 create_vs11_parser(&asm_ctx);
314 | VER_VS20
316 TRACE("Vertex shader 2.0\n");
317 create_vs20_parser(&asm_ctx);
319 | VER_VS2X
321 TRACE("Vertex shader 2.x\n");
322 create_vs2x_parser(&asm_ctx);
324 | VER_VS30
326 TRACE("Vertex shader 3.0\n");
327 create_vs30_parser(&asm_ctx);
329 | VER_PS10
331 TRACE("Pixel shader 1.0\n");
332 create_ps10_parser(&asm_ctx);
334 | VER_PS11
336 TRACE("Pixel shader 1.1\n");
337 create_ps11_parser(&asm_ctx);
339 | VER_PS12
341 TRACE("Pixel shader 1.2\n");
342 create_ps12_parser(&asm_ctx);
344 | VER_PS13
346 TRACE("Pixel shader 1.3\n");
347 create_ps13_parser(&asm_ctx);
349 | VER_PS14
351 TRACE("Pixel shader 1.4\n");
352 create_ps14_parser(&asm_ctx);
354 | VER_PS20
356 TRACE("Pixel shader 2.0\n");
357 create_ps20_parser(&asm_ctx);
359 | VER_PS2X
361 TRACE("Pixel shader 2.x\n");
362 create_ps2x_parser(&asm_ctx);
364 | VER_PS30
366 TRACE("Pixel shader 3.0\n");
367 create_ps30_parser(&asm_ctx);
370 instructions: /* empty */
371 | instructions complexinstr
373 /* Nothing to do */
376 complexinstr: instruction
380 | predicate instruction
382 TRACE("predicate\n");
383 asm_ctx.funcs->predicate(&asm_ctx, &$1);
385 | '+' instruction
387 TRACE("coissue\n");
388 asm_ctx.funcs->coissue(&asm_ctx);
391 instruction: INSTR_ADD omods dreg ',' sregs
393 TRACE("ADD\n");
394 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ADD, $2.mod, $2.shift, 0, &$3, &$5, 2);
396 | INSTR_NOP
398 TRACE("NOP\n");
399 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NOP, 0, 0, 0, 0, 0, 0);
401 | INSTR_MOV omods dreg ',' sregs
403 TRACE("MOV\n");
404 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOV, $2.mod, $2.shift, 0, &$3, &$5, 1);
406 | INSTR_SUB omods dreg ',' sregs
408 TRACE("SUB\n");
409 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SUB, $2.mod, $2.shift, 0, &$3, &$5, 2);
411 | INSTR_MAD omods dreg ',' sregs
413 TRACE("MAD\n");
414 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAD, $2.mod, $2.shift, 0, &$3, &$5, 3);
416 | INSTR_MUL omods dreg ',' sregs
418 TRACE("MUL\n");
419 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MUL, $2.mod, $2.shift, 0, &$3, &$5, 2);
421 | INSTR_RCP omods dreg ',' sregs
423 TRACE("RCP\n");
424 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RCP, $2.mod, $2.shift, 0, &$3, &$5, 1);
426 | INSTR_RSQ omods dreg ',' sregs
428 TRACE("RSQ\n");
429 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RSQ, $2.mod, $2.shift, 0, &$3, &$5, 1);
431 | INSTR_DP3 omods dreg ',' sregs
433 TRACE("DP3\n");
434 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP3, $2.mod, $2.shift, 0, &$3, &$5, 2);
436 | INSTR_DP4 omods dreg ',' sregs
438 TRACE("DP4\n");
439 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP4, $2.mod, $2.shift, 0, &$3, &$5, 2);
441 | INSTR_MIN omods dreg ',' sregs
443 TRACE("MIN\n");
444 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MIN, $2.mod, $2.shift, 0, &$3, &$5, 2);
446 | INSTR_MAX omods dreg ',' sregs
448 TRACE("MAX\n");
449 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAX, $2.mod, $2.shift, 0, &$3, &$5, 2);
451 | INSTR_SLT omods dreg ',' sregs
453 TRACE("SLT\n");
454 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SLT, $2.mod, $2.shift, 0, &$3, &$5, 2);
456 | INSTR_SGE omods dreg ',' sregs
458 TRACE("SGE\n");
459 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGE, $2.mod, $2.shift, 0, &$3, &$5, 2);
461 | INSTR_ABS omods dreg ',' sregs
463 TRACE("ABS\n");
464 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ABS, $2.mod, $2.shift, 0, &$3, &$5, 1);
466 | INSTR_EXP omods dreg ',' sregs
468 TRACE("EXP\n");
469 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXP, $2.mod, $2.shift, 0, &$3, &$5, 1);
471 | INSTR_LOG omods dreg ',' sregs
473 TRACE("LOG\n");
474 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOG, $2.mod, $2.shift, 0, &$3, &$5, 1);
476 | INSTR_LOGP omods dreg ',' sregs
478 TRACE("LOGP\n");
479 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOGP, $2.mod, $2.shift, 0, &$3, &$5, 1);
481 | INSTR_EXPP omods dreg ',' sregs
483 TRACE("EXPP\n");
484 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXPP, $2.mod, $2.shift, 0, &$3, &$5, 1);
486 | INSTR_DST omods dreg ',' sregs
488 TRACE("DST\n");
489 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DST, $2.mod, $2.shift, 0, &$3, &$5, 2);
491 | INSTR_LRP omods dreg ',' sregs
493 TRACE("LRP\n");
494 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LRP, $2.mod, $2.shift, 0, &$3, &$5, 3);
496 | INSTR_FRC omods dreg ',' sregs
498 TRACE("FRC\n");
499 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_FRC, $2.mod, $2.shift, 0, &$3, &$5, 1);
501 | INSTR_POW omods dreg ',' sregs
503 TRACE("POW\n");
504 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_POW, $2.mod, $2.shift, 0, &$3, &$5, 2);
506 | INSTR_CRS omods dreg ',' sregs
508 TRACE("CRS\n");
509 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CRS, $2.mod, $2.shift, 0, &$3, &$5, 2);
511 | INSTR_SGN omods dreg ',' sregs
513 TRACE("SGN\n");
514 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGN, $2.mod, $2.shift, 0, &$3, &$5, 3);
516 | INSTR_NRM omods dreg ',' sregs
518 TRACE("NRM\n");
519 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NRM, $2.mod, $2.shift, 0, &$3, &$5, 1);
521 | INSTR_SINCOS omods dreg ',' sregs
523 TRACE("SINCOS\n");
524 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SINCOS, $2.mod, $2.shift, 0, &$3, &$5, 1);
526 | INSTR_M4x4 omods dreg ',' sregs
528 TRACE("M4x4\n");
529 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
531 | INSTR_M4x3 omods dreg ',' sregs
533 TRACE("M4x3\n");
534 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
536 | INSTR_M3x4 omods dreg ',' sregs
538 TRACE("M3x4\n");
539 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
541 | INSTR_M3x3 omods dreg ',' sregs
543 TRACE("M3x3\n");
544 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
546 | INSTR_M3x2 omods dreg ',' sregs
548 TRACE("M3x2\n");
549 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x2, $2.mod, $2.shift, 0, &$3, &$5, 2);
551 | INSTR_DCL dclusage REG_OUTPUT
553 struct shader_reg reg;
554 TRACE("Output reg declaration\n");
555 ZeroMemory(&reg, sizeof(reg));
556 reg.type = BWRITERSPR_OUTPUT;
557 reg.regnum = $3;
558 reg.rel_reg = NULL;
559 reg.srcmod = 0;
560 reg.writemask = BWRITERSP_WRITEMASK_ALL;
561 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
563 | INSTR_DCL dclusage REG_OUTPUT writemask
565 struct shader_reg reg;
566 TRACE("Output reg declaration\n");
567 ZeroMemory(&reg, sizeof(reg));
568 reg.type = BWRITERSPR_OUTPUT;
569 reg.regnum = $3;
570 reg.rel_reg = NULL;
571 reg.srcmod = 0;
572 reg.writemask = $4;
573 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
575 | INSTR_DCL dclusage omods dcl_inputreg
577 struct shader_reg reg;
578 TRACE("Input reg declaration\n");
579 if($3.shift != 0) {
580 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
581 asm_ctx.line_no);
582 set_parse_status(&asm_ctx, PARSE_ERR);
584 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) ||
585 asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) {
586 asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n",
587 asm_ctx.line_no);
588 set_parse_status(&asm_ctx, PARSE_ERR);
590 ZeroMemory(&reg, sizeof(reg));
591 reg.type = $4.type;
592 reg.regnum = $4.regnum;
593 reg.rel_reg = NULL;
594 reg.srcmod = 0;
595 reg.writemask = BWRITERSP_WRITEMASK_ALL;
596 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, &reg);
598 | INSTR_DCL dclusage omods dcl_inputreg writemask
600 struct shader_reg reg;
601 TRACE("Input reg declaration\n");
602 if($3.shift != 0) {
603 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
604 asm_ctx.line_no);
605 set_parse_status(&asm_ctx, PARSE_ERR);
607 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) ||
608 asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) {
609 asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n",
610 asm_ctx.line_no);
611 set_parse_status(&asm_ctx, PARSE_ERR);
613 ZeroMemory(&reg, sizeof(reg));
614 reg.type = $4.type;
615 reg.regnum = $4.regnum;
616 reg.rel_reg = NULL;
617 reg.srcmod = 0;
618 reg.writemask = $5;
619 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, &reg);
621 | INSTR_DCL omods dcl_inputreg
623 struct shader_reg reg;
624 TRACE("Input reg declaration\n");
625 if($2.shift != 0) {
626 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
627 asm_ctx.line_no);
628 set_parse_status(&asm_ctx, PARSE_ERR);
630 if(asm_ctx.shader->type != ST_PIXEL) {
631 asmparser_message(&asm_ctx, "Line %u: Declaration needs a semantic\n",
632 asm_ctx.line_no);
633 set_parse_status(&asm_ctx, PARSE_ERR);
635 ZeroMemory(&reg, sizeof(reg));
636 reg.type = $3.type;
637 reg.regnum = $3.regnum;
638 reg.rel_reg = NULL;
639 reg.srcmod = 0;
640 reg.writemask = BWRITERSP_WRITEMASK_ALL;
641 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, &reg);
643 | INSTR_DCL omods dcl_inputreg writemask
645 struct shader_reg reg;
646 TRACE("Input reg declaration\n");
647 if($2.shift != 0) {
648 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
649 asm_ctx.line_no);
650 set_parse_status(&asm_ctx, PARSE_ERR);
652 if(asm_ctx.shader->type != ST_PIXEL) {
653 asmparser_message(&asm_ctx, "Line %u: Declaration needs a semantic\n",
654 asm_ctx.line_no);
655 set_parse_status(&asm_ctx, PARSE_ERR);
657 ZeroMemory(&reg, sizeof(reg));
658 reg.type = $3.type;
659 reg.regnum = $3.regnum;
660 reg.rel_reg = NULL;
661 reg.srcmod = 0;
662 reg.writemask = $4;
663 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, &reg);
665 | INSTR_DCL sampdcl omods REG_SAMPLER
667 TRACE("Sampler declared\n");
668 if($3.shift != 0) {
669 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
670 asm_ctx.line_no);
671 set_parse_status(&asm_ctx, PARSE_ERR);
673 asm_ctx.funcs->dcl_sampler(&asm_ctx, $2, $3.mod, $4, asm_ctx.line_no);
675 | INSTR_DCL omods REG_SAMPLER
677 TRACE("Sampler declared\n");
678 if($2.shift != 0) {
679 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
680 asm_ctx.line_no);
681 set_parse_status(&asm_ctx, PARSE_ERR);
683 if(asm_ctx.shader->type != ST_PIXEL) {
684 asmparser_message(&asm_ctx, "Line %u: Declaration needs a sampler type\n",
685 asm_ctx.line_no);
686 set_parse_status(&asm_ctx, PARSE_ERR);
688 asm_ctx.funcs->dcl_sampler(&asm_ctx, BWRITERSTT_UNKNOWN, $2.mod, $3, asm_ctx.line_no);
690 | INSTR_DCL sampdcl omods dcl_inputreg
692 TRACE("Error rule: sampler decl of input reg\n");
693 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of input regs is not valid\n",
694 asm_ctx.line_no);
695 set_parse_status(&asm_ctx, PARSE_WARN);
697 | INSTR_DCL sampdcl omods REG_OUTPUT
699 TRACE("Error rule: sampler decl of output reg\n");
700 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of output regs is not valid\n",
701 asm_ctx.line_no);
702 set_parse_status(&asm_ctx, PARSE_WARN);
704 | INSTR_DEF REG_CONSTFLOAT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
706 asm_ctx.funcs->constF(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val);
708 | INSTR_DEFI REG_CONSTINT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
710 asm_ctx.funcs->constI(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val);
712 | INSTR_DEFB REG_CONSTBOOL ',' IMMBOOL
714 asm_ctx.funcs->constB(&asm_ctx, $2, $4);
716 | INSTR_REP sregs
718 TRACE("REP\n");
719 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_REP, 0, 0, 0, 0, &$2, 1);
721 | INSTR_ENDREP
723 TRACE("ENDREP\n");
724 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDREP, 0, 0, 0, 0, 0, 0);
726 | INSTR_IF sregs
728 TRACE("IF\n");
729 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IF, 0, 0, 0, 0, &$2, 1);
731 | INSTR_IF comp sregs
733 TRACE("IFC\n");
734 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IFC, 0, 0, $2, 0, &$3, 2);
736 | INSTR_ELSE
738 TRACE("ELSE\n");
739 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ELSE, 0, 0, 0, 0, 0, 0);
741 | INSTR_ENDIF
743 TRACE("ENDIF\n");
744 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDIF, 0, 0, 0, 0, 0, 0);
746 | INSTR_BREAK
748 TRACE("BREAK\n");
749 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAK, 0, 0, 0, 0, 0, 0);
751 | INSTR_BREAK comp sregs
753 TRACE("BREAKC\n");
754 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKC, 0, 0, $2, 0, &$3, 2);
756 | INSTR_BREAKP sregs
758 TRACE("BREAKP\n");
759 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKP, 0, 0, 0, 0, &$2, 1);
761 | INSTR_CALL sregs
763 TRACE("CALL\n");
764 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALL, 0, 0, 0, 0, &$2, 1);
766 | INSTR_CALLNZ sregs
768 TRACE("CALLNZ\n");
769 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALLNZ, 0, 0, 0, 0, &$2, 2);
771 | INSTR_LOOP sregs
773 TRACE("LOOP\n");
774 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOOP, 0, 0, 0, 0, &$2, 2);
776 | INSTR_RET
778 TRACE("RET\n");
779 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RET, 0, 0, 0, 0, 0, 0);
781 | INSTR_ENDLOOP
783 TRACE("ENDLOOP\n");
784 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDLOOP, 0, 0, 0, 0, 0, 0);
786 | INSTR_LABEL sregs
788 TRACE("LABEL\n");
789 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LABEL, 0, 0, 0, 0, &$2, 1);
791 | INSTR_SETP comp dreg ',' sregs
793 TRACE("SETP\n");
794 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SETP, 0, 0, $2, &$3, &$5, 2);
796 | INSTR_TEXLDL omods dreg ',' sregs
798 TRACE("TEXLDL\n");
799 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDL, $2.mod, $2.shift, 0, &$3, &$5, 2);
801 | INSTR_LIT omods dreg ',' sregs
803 TRACE("LIT\n");
804 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LIT, $2.mod, $2.shift, 0, &$3, &$5, 1);
806 | INSTR_MOVA omods dreg ',' sregs
808 TRACE("MOVA\n");
809 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOVA, $2.mod, $2.shift, 0, &$3, &$5, 1);
811 | INSTR_CND omods dreg ',' sregs
813 TRACE("CND\n");
814 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CND, $2.mod, $2.shift, 0, &$3, &$5, 3);
816 | INSTR_CMP omods dreg ',' sregs
818 TRACE("CMP\n");
819 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CMP, $2.mod, $2.shift, 0, &$3, &$5, 3);
821 | INSTR_DP2ADD omods dreg ',' sregs
823 TRACE("DP2ADD\n");
824 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP2ADD, $2.mod, $2.shift, 0, &$3, &$5, 3);
826 | INSTR_TEXCOORD omods dreg
828 TRACE("TEXCOORD\n");
829 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXCOORD, $2.mod, $2.shift, 0, &$3, 0, 0);
831 | INSTR_TEXCRD omods dreg ',' sregs
833 TRACE("TEXCRD\n");
834 /* texcoord and texcrd share the same opcode */
835 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXCOORD, $2.mod, $2.shift, 0, &$3, &$5, 1);
837 | INSTR_TEXKILL dreg
839 TRACE("TEXKILL\n");
840 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXKILL, 0, 0, 0, &$2, 0, 0);
842 | INSTR_TEX omods dreg
844 TRACE("TEX\n");
845 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, 0, 0);
847 | INSTR_TEXDEPTH omods dreg
849 TRACE("TEXDEPTH\n");
850 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDEPTH, $2.mod, $2.shift, 0, &$3, 0, 0);
852 | INSTR_TEXLD omods dreg ',' sregs
854 TRACE("TEXLD\n");
855 /* There is more than one acceptable syntax for texld:
856 with 1 sreg (PS 1.4) or
857 with 2 sregs (PS 2.0+)
858 Moreover, texld shares the same opcode as the tex instruction,
859 so there are a total of 3 valid syntaxes
860 These variations are handled in asmparser.c */
861 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, &$5, 2);
863 | INSTR_TEXLDP omods dreg ',' sregs
865 TRACE("TEXLDP\n");
866 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDP, $2.mod, $2.shift, 0, &$3, &$5, 2);
868 | INSTR_TEXLDB omods dreg ',' sregs
870 TRACE("TEXLDB\n");
871 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDB, $2.mod, $2.shift, 0, &$3, &$5, 2);
873 | INSTR_TEXBEM omods dreg ',' sregs
875 TRACE("TEXBEM\n");
876 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXBEM, $2.mod, $2.shift, 0, &$3, &$5, 1);
878 | INSTR_TEXBEML omods dreg ',' sregs
880 TRACE("TEXBEML\n");
881 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXBEML, $2.mod, $2.shift, 0, &$3, &$5, 1);
883 | INSTR_TEXREG2AR omods dreg ',' sregs
885 TRACE("TEXREG2AR\n");
886 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2AR, $2.mod, $2.shift, 0, &$3, &$5, 1);
888 | INSTR_TEXREG2GB omods dreg ',' sregs
890 TRACE("TEXREG2GB\n");
891 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2GB, $2.mod, $2.shift, 0, &$3, &$5, 1);
893 | INSTR_TEXREG2RGB omods dreg ',' sregs
895 TRACE("TEXREG2RGB\n");
896 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2RGB, $2.mod, $2.shift, 0, &$3, &$5, 1);
898 | INSTR_TEXM3x2PAD omods dreg ',' sregs
900 TRACE("TEXM3x2PAD\n");
901 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2PAD, $2.mod, $2.shift, 0, &$3, &$5, 1);
903 | INSTR_TEXM3x3PAD omods dreg ',' sregs
905 TRACE("INSTR_TEXM3x3PAD\n");
906 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3PAD, $2.mod, $2.shift, 0, &$3, &$5, 1);
908 | INSTR_TEXM3x3SPEC omods dreg ',' sregs
910 TRACE("TEXM3x3SPEC\n");
911 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3SPEC, $2.mod, $2.shift, 0, &$3, &$5, 2);
913 | INSTR_TEXM3x3VSPEC omods dreg ',' sregs
915 TRACE("TEXM3x3VSPEC\n");
916 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3VSPEC, $2.mod, $2.shift, 0, &$3, &$5, 1);
918 | INSTR_TEXM3x3TEX omods dreg ',' sregs
920 TRACE("TEXM3x3TEX\n");
921 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3TEX, $2.mod, $2.shift, 0, &$3, &$5, 1);
923 | INSTR_TEXDP3TEX omods dreg ',' sregs
925 TRACE("TEXDP3TEX\n");
926 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDP3TEX, $2.mod, $2.shift, 0, &$3, &$5, 1);
928 | INSTR_TEXM3x2DEPTH omods dreg ',' sregs
930 TRACE("TEXM3x2DEPTH\n");
931 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2DEPTH, $2.mod, $2.shift, 0, &$3, &$5, 1);
933 | INSTR_TEXM3x2TEX omods dreg ',' sregs
935 TRACE("TEXM3x2TEX\n");
936 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2TEX, $2.mod, $2.shift, 0, &$3, &$5, 1);
938 | INSTR_TEXDP3 omods dreg ',' sregs
940 TRACE("TEXDP3\n");
941 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDP3, $2.mod, $2.shift, 0, &$3, &$5, 1);
943 | INSTR_TEXM3x3 omods dreg ',' sregs
945 TRACE("TEXM3x3\n");
946 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3, $2.mod, $2.shift, 0, &$3, &$5, 1);
948 | INSTR_BEM omods dreg ',' sregs
950 TRACE("BEM\n");
951 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BEM, $2.mod, $2.shift, 0, &$3, &$5, 2);
953 | INSTR_DSX omods dreg ',' sregs
955 TRACE("DSX\n");
956 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSX, $2.mod, $2.shift, 0, &$3, &$5, 1);
958 | INSTR_DSY omods dreg ',' sregs
960 TRACE("DSY\n");
961 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSY, $2.mod, $2.shift, 0, &$3, &$5, 1);
963 | INSTR_TEXLDD omods dreg ',' sregs
965 TRACE("TEXLDD\n");
966 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDD, $2.mod, $2.shift, 0, &$3, &$5, 4);
968 | INSTR_PHASE
970 TRACE("PHASE\n");
971 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_PHASE, 0, 0, 0, 0, 0, 0);
975 dreg: dreg_name rel_reg
977 $$.regnum = $1.regnum;
978 $$.type = $1.type;
979 $$.writemask = BWRITERSP_WRITEMASK_ALL;
980 $$.srcmod = BWRITERSPSM_NONE;
981 set_rel_reg(&$$, &$2);
983 | dreg_name writemask
985 $$.regnum = $1.regnum;
986 $$.type = $1.type;
987 $$.writemask = $2;
988 $$.srcmod = BWRITERSPSM_NONE;
989 $$.rel_reg = NULL;
992 dreg_name: REG_TEMP
994 $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
996 | REG_OUTPUT
998 $$.regnum = $1; $$.type = BWRITERSPR_OUTPUT;
1000 | REG_INPUT
1002 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1004 | REG_CONSTFLOAT
1006 asmparser_message(&asm_ctx, "Line %u: Register c%u is not a valid destination register\n",
1007 asm_ctx.line_no, $1);
1008 set_parse_status(&asm_ctx, PARSE_WARN);
1010 | REG_CONSTINT
1012 asmparser_message(&asm_ctx, "Line %u: Register i%u is not a valid destination register\n",
1013 asm_ctx.line_no, $1);
1014 set_parse_status(&asm_ctx, PARSE_WARN);
1016 | REG_CONSTBOOL
1018 asmparser_message(&asm_ctx, "Line %u: Register b%u is not a valid destination register\n",
1019 asm_ctx.line_no, $1);
1020 set_parse_status(&asm_ctx, PARSE_WARN);
1022 | REG_TEXTURE
1024 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1026 | REG_TEXCRDOUT
1028 $$.regnum = $1; $$.type = BWRITERSPR_TEXCRDOUT;
1030 | REG_SAMPLER
1032 asmparser_message(&asm_ctx, "Line %u: Register s%u is not a valid destination register\n",
1033 asm_ctx.line_no, $1);
1034 set_parse_status(&asm_ctx, PARSE_WARN);
1036 | REG_OPOS
1038 $$.regnum = BWRITERSRO_POSITION; $$.type = BWRITERSPR_RASTOUT;
1040 | REG_OPTS
1042 $$.regnum = BWRITERSRO_POINT_SIZE; $$.type = BWRITERSPR_RASTOUT;
1044 | REG_OFOG
1046 $$.regnum = BWRITERSRO_FOG; $$.type = BWRITERSPR_RASTOUT;
1048 | REG_VERTEXCOLOR
1050 $$.regnum = $1; $$.type = BWRITERSPR_ATTROUT;
1052 | REG_FRAGCOLOR
1054 $$.regnum = $1; $$.type = BWRITERSPR_COLOROUT;
1056 | REG_FRAGDEPTH
1058 $$.regnum = 0; $$.type = BWRITERSPR_DEPTHOUT;
1060 | REG_PREDICATE
1062 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
1064 | REG_VPOS
1066 asmparser_message(&asm_ctx, "Line %u: Register vPos is not a valid destination register\n",
1067 asm_ctx.line_no);
1068 set_parse_status(&asm_ctx, PARSE_WARN);
1070 | REG_VFACE
1072 asmparser_message(&asm_ctx, "Line %u: Register vFace is not a valid destination register\n",
1073 asm_ctx.line_no);
1074 set_parse_status(&asm_ctx, PARSE_WARN);
1076 | REG_ADDRESS
1078 /* index 0 is hardcoded for the addr register */
1079 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1081 | REG_LOOP
1083 asmparser_message(&asm_ctx, "Line %u: Register aL is not a valid destination register\n",
1084 asm_ctx.line_no);
1085 set_parse_status(&asm_ctx, PARSE_WARN);
1088 writemask: '.' wm_components
1090 if($2.writemask == SWIZZLE_ERR) {
1091 asmparser_message(&asm_ctx, "Line %u: Invalid writemask specified\n",
1092 asm_ctx.line_no);
1093 set_parse_status(&asm_ctx, PARSE_ERR);
1094 /* Provide a correct writemask to prevent following complaints */
1095 $$ = BWRITERSP_WRITEMASK_ALL;
1097 else {
1098 $$ = $2.writemask;
1099 TRACE("Writemask: %x\n", $$);
1103 wm_components: COMPONENT
1105 $$.writemask = 1 << $1;
1106 $$.last = $1;
1107 $$.idx = 1;
1109 | wm_components COMPONENT
1111 if($1.writemask == SWIZZLE_ERR || $1.idx == 4)
1112 /* Wrong writemask */
1113 $$.writemask = SWIZZLE_ERR;
1114 else {
1115 if($2 <= $1.last)
1116 $$.writemask = SWIZZLE_ERR;
1117 else {
1118 $$.writemask = $1.writemask | (1 << $2);
1119 $$.idx = $1.idx + 1;
1124 swizzle: /* empty */
1126 $$ = BWRITERVS_NOSWIZZLE;
1127 TRACE("Default swizzle: %08x\n", $$);
1129 | '.' sw_components
1131 if($2.swizzle == SWIZZLE_ERR) {
1132 asmparser_message(&asm_ctx, "Line %u: Invalid swizzle\n",
1133 asm_ctx.line_no);
1134 set_parse_status(&asm_ctx, PARSE_ERR);
1135 /* Provide a correct swizzle to prevent following complaints */
1136 $$ = BWRITERVS_NOSWIZZLE;
1138 else {
1139 DWORD last, i;
1141 $$ = $2.swizzle << BWRITERVS_SWIZZLE_SHIFT;
1142 /* Fill the swizzle by extending the last component */
1143 last = ($2.swizzle >> 2 * ($2.idx - 1)) & 0x03;
1144 for(i = $2.idx; i < 4; i++){
1145 $$ |= last << (BWRITERVS_SWIZZLE_SHIFT + 2 * i);
1147 TRACE("Got a swizzle: %08x\n", $$);
1151 sw_components: COMPONENT
1153 $$.swizzle = $1;
1154 $$.idx = 1;
1156 | sw_components COMPONENT
1158 if($1.idx == 4) {
1159 /* Too many sw_components */
1160 $$.swizzle = SWIZZLE_ERR;
1161 $$.idx = 4;
1163 else {
1164 $$.swizzle = $1.swizzle | ($2 << 2 * $1.idx);
1165 $$.idx = $1.idx + 1;
1169 omods: /* Empty */
1171 $$.mod = 0;
1172 $$.shift = 0;
1174 | omods omodifier
1176 $$.mod = $1.mod | $2.mod;
1177 if($1.shift && $2.shift) {
1178 asmparser_message(&asm_ctx, "Line %u: More than one shift flag\n",
1179 asm_ctx.line_no);
1180 set_parse_status(&asm_ctx, PARSE_ERR);
1181 $$.shift = $1.shift;
1182 } else {
1183 $$.shift = $1.shift | $2.shift;
1187 omodifier: SHIFT_X2
1189 $$.mod = 0;
1190 $$.shift = 1;
1192 | SHIFT_X4
1194 $$.mod = 0;
1195 $$.shift = 2;
1197 | SHIFT_X8
1199 $$.mod = 0;
1200 $$.shift = 3;
1202 | SHIFT_D2
1204 $$.mod = 0;
1205 $$.shift = 15;
1207 | SHIFT_D4
1209 $$.mod = 0;
1210 $$.shift = 14;
1212 | SHIFT_D8
1214 $$.mod = 0;
1215 $$.shift = 13;
1217 | MOD_SAT
1219 $$.mod = BWRITERSPDM_SATURATE;
1220 $$.shift = 0;
1222 | MOD_PP
1224 $$.mod = BWRITERSPDM_PARTIALPRECISION;
1225 $$.shift = 0;
1227 | MOD_CENTROID
1229 $$.mod = BWRITERSPDM_MSAMPCENTROID;
1230 $$.shift = 0;
1233 sregs: sreg
1235 $$.reg[0] = $1;
1236 $$.count = 1;
1238 | sregs ',' sreg
1240 if($$.count == MAX_SRC_REGS){
1241 asmparser_message(&asm_ctx, "Line %u: Too many source registers in this instruction\n",
1242 asm_ctx.line_no);
1243 set_parse_status(&asm_ctx, PARSE_ERR);
1245 else
1246 $$.reg[$$.count++] = $3;
1249 sreg: sreg_name rel_reg swizzle
1251 $$.type = $1.type;
1252 $$.regnum = $1.regnum;
1253 $$.swizzle = $3;
1254 $$.srcmod = BWRITERSPSM_NONE;
1255 set_rel_reg(&$$, &$2);
1257 | sreg_name rel_reg smod swizzle
1259 $$.type = $1.type;
1260 $$.regnum = $1.regnum;
1261 set_rel_reg(&$$, &$2);
1262 $$.srcmod = $3;
1263 $$.swizzle = $4;
1265 | '-' sreg_name rel_reg swizzle
1267 $$.type = $2.type;
1268 $$.regnum = $2.regnum;
1269 $$.srcmod = BWRITERSPSM_NEG;
1270 set_rel_reg(&$$, &$3);
1271 $$.swizzle = $4;
1273 | '-' sreg_name rel_reg smod swizzle
1275 $$.type = $2.type;
1276 $$.regnum = $2.regnum;
1277 set_rel_reg(&$$, &$3);
1278 switch($4) {
1279 case BWRITERSPSM_BIAS: $$.srcmod = BWRITERSPSM_BIASNEG; break;
1280 case BWRITERSPSM_X2: $$.srcmod = BWRITERSPSM_X2NEG; break;
1281 case BWRITERSPSM_SIGN: $$.srcmod = BWRITERSPSM_SIGNNEG; break;
1282 case BWRITERSPSM_ABS: $$.srcmod = BWRITERSPSM_ABSNEG; break;
1283 case BWRITERSPSM_DZ:
1284 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DZ\n",
1285 asm_ctx.line_no);
1286 set_parse_status(&asm_ctx, PARSE_ERR);
1287 break;
1288 case BWRITERSPSM_DW:
1289 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DW\n",
1290 asm_ctx.line_no);
1291 set_parse_status(&asm_ctx, PARSE_ERR);
1292 break;
1293 default:
1294 FIXME("Unhandled combination of NEGATE and %u\n", $4);
1296 $$.swizzle = $5;
1298 | IMMVAL '-' sreg_name rel_reg swizzle
1300 if($1.val != 1.0 || (!$1.integer)) {
1301 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP, "
1302 "%g - reg found\n", asm_ctx.line_no, $1.val);
1303 set_parse_status(&asm_ctx, PARSE_ERR);
1305 /* Complement - not compatible with other source modifiers */
1306 $$.type = $3.type;
1307 $$.regnum = $3.regnum;
1308 $$.srcmod = BWRITERSPSM_COMP;
1309 set_rel_reg(&$$, &$4);
1310 $$.swizzle = $5;
1312 | IMMVAL '-' sreg_name rel_reg smod swizzle
1314 /* For nicer error reporting */
1315 if($1.val != 1.0 || (!$1.integer)) {
1316 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP\n",
1317 asm_ctx.line_no);
1318 set_parse_status(&asm_ctx, PARSE_ERR);
1319 } else {
1320 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: D3DSPSM_COMP and %s\n",
1321 asm_ctx.line_no,
1322 debug_print_srcmod($5));
1323 set_parse_status(&asm_ctx, PARSE_ERR);
1326 | SMOD_NOT sreg_name swizzle
1328 $$.type = $2.type;
1329 $$.regnum = $2.regnum;
1330 $$.rel_reg = NULL;
1331 $$.srcmod = BWRITERSPSM_NOT;
1332 $$.swizzle = $3;
1335 rel_reg: /* empty */
1337 $$.has_rel_reg = FALSE;
1338 $$.additional_offset = 0;
1340 | '[' immsum ']'
1342 $$.has_rel_reg = FALSE;
1343 $$.additional_offset = $2.val;
1345 | '[' relreg_name swizzle ']'
1347 $$.has_rel_reg = TRUE;
1348 $$.type = $2.type;
1349 $$.additional_offset = 0;
1350 $$.rel_regnum = $2.regnum;
1351 $$.swizzle = $3;
1353 | '[' immsum '+' relreg_name swizzle ']'
1355 $$.has_rel_reg = TRUE;
1356 $$.type = $4.type;
1357 $$.additional_offset = $2.val;
1358 $$.rel_regnum = $4.regnum;
1359 $$.swizzle = $5;
1361 | '[' relreg_name swizzle '+' immsum ']'
1363 $$.has_rel_reg = TRUE;
1364 $$.type = $2.type;
1365 $$.additional_offset = $5.val;
1366 $$.rel_regnum = $2.regnum;
1367 $$.swizzle = $3;
1369 | '[' immsum '+' relreg_name swizzle '+' immsum ']'
1371 $$.has_rel_reg = TRUE;
1372 $$.type = $4.type;
1373 $$.additional_offset = $2.val + $7.val;
1374 $$.rel_regnum = $4.regnum;
1375 $$.swizzle = $5;
1378 immsum: IMMVAL
1380 if(!$1.integer) {
1381 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1382 asm_ctx.line_no, $1.val);
1383 set_parse_status(&asm_ctx, PARSE_ERR);
1385 $$.val = $1.val;
1387 | immsum '+' IMMVAL
1389 if(!$3.integer) {
1390 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1391 asm_ctx.line_no, $3.val);
1392 set_parse_status(&asm_ctx, PARSE_ERR);
1394 $$.val = $1.val + $3.val;
1397 smod: SMOD_BIAS
1399 $$ = BWRITERSPSM_BIAS;
1401 | SHIFT_X2
1403 $$ = BWRITERSPSM_X2;
1405 | SMOD_SCALEBIAS
1407 $$ = BWRITERSPSM_SIGN;
1409 | SMOD_DZ
1411 $$ = BWRITERSPSM_DZ;
1413 | SMOD_DW
1415 $$ = BWRITERSPSM_DW;
1417 | SMOD_ABS
1419 $$ = BWRITERSPSM_ABS;
1422 relreg_name: REG_ADDRESS
1424 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1426 | REG_LOOP
1428 $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1431 sreg_name: REG_TEMP
1433 $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
1435 | REG_OUTPUT
1437 asmparser_message(&asm_ctx, "Line %u: Register o%u is not a valid source register\n",
1438 asm_ctx.line_no, $1);
1439 set_parse_status(&asm_ctx, PARSE_WARN);
1441 | REG_INPUT
1443 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1445 | REG_CONSTFLOAT
1447 $$.regnum = $1; $$.type = BWRITERSPR_CONST;
1449 | REG_CONSTINT
1451 $$.regnum = $1; $$.type = BWRITERSPR_CONSTINT;
1453 | REG_CONSTBOOL
1455 $$.regnum = $1; $$.type = BWRITERSPR_CONSTBOOL;
1457 | REG_TEXTURE
1459 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1461 | REG_TEXCRDOUT
1463 asmparser_message(&asm_ctx, "Line %u: Register oT%u is not a valid source register\n",
1464 asm_ctx.line_no, $1);
1465 set_parse_status(&asm_ctx, PARSE_WARN);
1467 | REG_SAMPLER
1469 $$.regnum = $1; $$.type = BWRITERSPR_SAMPLER;
1471 | REG_OPOS
1473 asmparser_message(&asm_ctx, "Line %u: Register oPos is not a valid source register\n",
1474 asm_ctx.line_no);
1475 set_parse_status(&asm_ctx, PARSE_WARN);
1477 | REG_OFOG
1479 asmparser_message(&asm_ctx, "Line %u: Register oFog is not a valid source register\n",
1480 asm_ctx.line_no);
1481 set_parse_status(&asm_ctx, PARSE_WARN);
1483 | REG_VERTEXCOLOR
1485 asmparser_message(&asm_ctx, "Line %u: Register oD%u is not a valid source register\n",
1486 asm_ctx.line_no, $1);
1487 set_parse_status(&asm_ctx, PARSE_WARN);
1489 | REG_FRAGCOLOR
1491 asmparser_message(&asm_ctx, "Line %u: Register oC%u is not a valid source register\n",
1492 asm_ctx.line_no, $1);
1493 set_parse_status(&asm_ctx, PARSE_WARN);
1495 | REG_FRAGDEPTH
1497 asmparser_message(&asm_ctx, "Line %u: Register oDepth is not a valid source register\n",
1498 asm_ctx.line_no);
1499 set_parse_status(&asm_ctx, PARSE_WARN);
1501 | REG_PREDICATE
1503 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
1505 | REG_VPOS
1507 $$.regnum = 0; $$.type = BWRITERSPR_MISCTYPE;
1509 | REG_VFACE
1511 $$.regnum = 1; $$.type = BWRITERSPR_MISCTYPE;
1513 | REG_ADDRESS
1515 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1517 | REG_LOOP
1519 $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1521 | REG_LABEL
1523 $$.regnum = $1; $$.type = BWRITERSPR_LABEL;
1526 comp: COMP_GT { $$ = BWRITER_COMPARISON_GT; }
1527 | COMP_LT { $$ = BWRITER_COMPARISON_LT; }
1528 | COMP_GE { $$ = BWRITER_COMPARISON_GE; }
1529 | COMP_LE { $$ = BWRITER_COMPARISON_LE; }
1530 | COMP_EQ { $$ = BWRITER_COMPARISON_EQ; }
1531 | COMP_NE { $$ = BWRITER_COMPARISON_NE; }
1533 dclusage: USAGE_POSITION
1535 TRACE("dcl_position%u\n", $1);
1536 $$.regnum = $1;
1537 $$.dclusage = BWRITERDECLUSAGE_POSITION;
1539 | USAGE_BLENDWEIGHT
1541 TRACE("dcl_blendweight%u\n", $1);
1542 $$.regnum = $1;
1543 $$.dclusage = BWRITERDECLUSAGE_BLENDWEIGHT;
1545 | USAGE_BLENDINDICES
1547 TRACE("dcl_blendindices%u\n", $1);
1548 $$.regnum = $1;
1549 $$.dclusage = BWRITERDECLUSAGE_BLENDINDICES;
1551 | USAGE_NORMAL
1553 TRACE("dcl_normal%u\n", $1);
1554 $$.regnum = $1;
1555 $$.dclusage = BWRITERDECLUSAGE_NORMAL;
1557 | USAGE_PSIZE
1559 TRACE("dcl_psize%u\n", $1);
1560 $$.regnum = $1;
1561 $$.dclusage = BWRITERDECLUSAGE_PSIZE;
1563 | USAGE_TEXCOORD
1565 TRACE("dcl_texcoord%u\n", $1);
1566 $$.regnum = $1;
1567 $$.dclusage = BWRITERDECLUSAGE_TEXCOORD;
1569 | USAGE_TANGENT
1571 TRACE("dcl_tangent%u\n", $1);
1572 $$.regnum = $1;
1573 $$.dclusage = BWRITERDECLUSAGE_TANGENT;
1575 | USAGE_BINORMAL
1577 TRACE("dcl_binormal%u\n", $1);
1578 $$.regnum = $1;
1579 $$.dclusage = BWRITERDECLUSAGE_BINORMAL;
1581 | USAGE_TESSFACTOR
1583 TRACE("dcl_tessfactor%u\n", $1);
1584 $$.regnum = $1;
1585 $$.dclusage = BWRITERDECLUSAGE_TESSFACTOR;
1587 | USAGE_POSITIONT
1589 TRACE("dcl_positiont%u\n", $1);
1590 $$.regnum = $1;
1591 $$.dclusage = BWRITERDECLUSAGE_POSITIONT;
1593 | USAGE_COLOR
1595 TRACE("dcl_color%u\n", $1);
1596 $$.regnum = $1;
1597 $$.dclusage = BWRITERDECLUSAGE_COLOR;
1599 | USAGE_FOG
1601 TRACE("dcl_fog%u\n", $1);
1602 $$.regnum = $1;
1603 $$.dclusage = BWRITERDECLUSAGE_FOG;
1605 | USAGE_DEPTH
1607 TRACE("dcl_depth%u\n", $1);
1608 $$.regnum = $1;
1609 $$.dclusage = BWRITERDECLUSAGE_DEPTH;
1611 | USAGE_SAMPLE
1613 TRACE("dcl_sample%u\n", $1);
1614 $$.regnum = $1;
1615 $$.dclusage = BWRITERDECLUSAGE_SAMPLE;
1618 dcl_inputreg: REG_INPUT
1620 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1622 | REG_TEXTURE
1624 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1627 sampdcl: SAMPTYPE_1D
1629 $$ = BWRITERSTT_1D;
1631 | SAMPTYPE_2D
1633 $$ = BWRITERSTT_2D;
1635 | SAMPTYPE_CUBE
1637 $$ = BWRITERSTT_CUBE;
1639 | SAMPTYPE_VOLUME
1641 $$ = BWRITERSTT_VOLUME;
1644 predicate: '(' REG_PREDICATE swizzle ')'
1646 $$.type = BWRITERSPR_PREDICATE;
1647 $$.regnum = 0;
1648 $$.rel_reg = NULL;
1649 $$.srcmod = BWRITERSPSM_NONE;
1650 $$.swizzle = $3;
1652 | '(' SMOD_NOT REG_PREDICATE swizzle ')'
1654 $$.type = BWRITERSPR_PREDICATE;
1655 $$.regnum = 0;
1656 $$.rel_reg = NULL;
1657 $$.srcmod = BWRITERSPSM_NOT;
1658 $$.swizzle = $4;
1663 void asmshader_error (char const *s) {
1664 asmparser_message(&asm_ctx, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no, s);
1665 set_parse_status(&asm_ctx, PARSE_ERR);
1668 /* Error reporting function */
1669 void asmparser_message(struct asm_parser *ctx, const char *fmt, ...) {
1670 va_list args;
1671 char* newbuffer;
1672 int rc, newsize;
1674 if(ctx->messagecapacity == 0) {
1675 ctx->messages = asm_alloc(MESSAGEBUFFER_INITIAL_SIZE);
1676 if(ctx->messages == NULL) {
1677 ERR("Error allocating memory for parser messages\n");
1678 return;
1680 ctx->messagecapacity = MESSAGEBUFFER_INITIAL_SIZE;
1683 while(1) {
1684 va_start(args, fmt);
1685 rc = vsnprintf(ctx->messages + ctx->messagesize,
1686 ctx->messagecapacity - ctx->messagesize, fmt, args);
1687 va_end(args);
1689 if (rc < 0 || /* C89 */
1690 rc >= ctx->messagecapacity - ctx->messagesize) { /* C99 */
1691 /* Resize the buffer */
1692 newsize = ctx->messagecapacity * 2;
1693 newbuffer = asm_realloc(ctx->messages, newsize);
1694 if(newbuffer == NULL){
1695 ERR("Error reallocating memory for parser messages\n");
1696 return;
1698 ctx->messages = newbuffer;
1699 ctx->messagecapacity = newsize;
1700 } else {
1701 ctx->messagesize += rc;
1702 return;
1707 /* New status is the worst between current status and parameter value */
1708 void set_parse_status(struct asm_parser *ctx, enum parse_status status) {
1709 if(status == PARSE_ERR) ctx->status = PARSE_ERR;
1710 else if(status == PARSE_WARN && ctx->status == PARSE_SUCCESS) ctx->status = PARSE_WARN;
1713 struct bwriter_shader *parse_asm_shader(char **messages) {
1714 struct bwriter_shader *ret = NULL;
1716 asm_ctx.shader = NULL;
1717 asm_ctx.status = PARSE_SUCCESS;
1718 asm_ctx.messagesize = asm_ctx.messagecapacity = 0;
1719 asm_ctx.line_no = 1;
1721 asmshader_parse();
1723 if(asm_ctx.status != PARSE_ERR) ret = asm_ctx.shader;
1724 else if(asm_ctx.shader) SlDeleteShader(asm_ctx.shader);
1726 if(messages) {
1727 if(asm_ctx.messagesize) {
1728 /* Shrink the buffer to the used size */
1729 *messages = asm_realloc(asm_ctx.messages, asm_ctx.messagesize + 1);
1730 if(!*messages) {
1731 ERR("Out of memory, no messages reported\n");
1732 asm_free(asm_ctx.messages);
1734 } else {
1735 *messages = NULL;
1737 } else {
1738 if(asm_ctx.messagecapacity) asm_free(asm_ctx.messages);
1741 return ret;