d3dx9: Add shift modifiers parsing to the shader assembler.
[wine/multimedia.git] / dlls / d3dx9_36 / asmshader.y
blob503af1d2131d2879ead805e34e6d4f49a2aeeae0
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_CMP
152 %token INSTR_DP2ADD
153 %token INSTR_TEXKILL
154 %token INSTR_TEXLD
155 %token INSTR_DSX
156 %token INSTR_DSY
157 %token INSTR_TEXLDP
158 %token INSTR_TEXLDB
159 %token INSTR_TEXLDD
161 /* Registers */
162 %token <regnum> REG_TEMP
163 %token <regnum> REG_OUTPUT
164 %token <regnum> REG_INPUT
165 %token <regnum> REG_CONSTFLOAT
166 %token <regnum> REG_CONSTINT
167 %token <regnum> REG_CONSTBOOL
168 %token <regnum> REG_TEXTURE
169 %token <regnum> REG_SAMPLER
170 %token <regnum> REG_TEXCRDOUT
171 %token REG_OPOS
172 %token REG_OFOG
173 %token REG_OPTS
174 %token <regnum> REG_VERTEXCOLOR
175 %token <regnum> REG_FRAGCOLOR
176 %token REG_FRAGDEPTH
177 %token REG_VPOS
178 %token REG_VFACE
179 %token REG_ADDRESS
180 %token REG_LOOP
181 %token REG_PREDICATE
182 %token <regnum> REG_LABEL
184 /* Version tokens */
185 %token VER_VS10
186 %token VER_VS11
187 %token VER_VS20
188 %token VER_VS2X
189 %token VER_VS30
191 %token VER_PS10
192 %token VER_PS11
193 %token VER_PS12
194 %token VER_PS13
195 %token VER_PS14
196 %token VER_PS20
197 %token VER_PS2X
198 %token VER_PS30
200 /* Output modifiers */
201 %token SHIFT_X2
202 %token SHIFT_X4
203 %token SHIFT_X8
204 %token SHIFT_D2
205 %token SHIFT_D4
206 %token SHIFT_D8
207 %token MOD_SAT
208 %token MOD_PP
209 %token MOD_CENTROID
211 /* Compare tokens */
212 %token COMP_GT
213 %token COMP_LT
214 %token COMP_GE
215 %token COMP_LE
216 %token COMP_EQ
217 %token COMP_NE
219 /* Source register modifiers */
220 %token SMOD_BIAS
221 %token SMOD_SCALEBIAS
222 %token SMOD_DZ
223 %token SMOD_DW
224 %token SMOD_ABS
225 %token SMOD_NOT
227 /* Sampler types */
228 %token SAMPTYPE_1D
229 %token SAMPTYPE_2D
230 %token SAMPTYPE_CUBE
231 %token SAMPTYPE_VOLUME
233 /* Usage declaration tokens */
234 %token <regnum> USAGE_POSITION
235 %token <regnum> USAGE_BLENDWEIGHT
236 %token <regnum> USAGE_BLENDINDICES
237 %token <regnum> USAGE_NORMAL
238 %token <regnum> USAGE_PSIZE
239 %token <regnum> USAGE_TEXCOORD
240 %token <regnum> USAGE_TANGENT
241 %token <regnum> USAGE_BINORMAL
242 %token <regnum> USAGE_TESSFACTOR
243 %token <regnum> USAGE_POSITIONT
244 %token <regnum> USAGE_COLOR
245 %token <regnum> USAGE_FOG
246 %token <regnum> USAGE_DEPTH
247 %token <regnum> USAGE_SAMPLE
249 /* Misc stuff */
250 %token <component> COMPONENT
251 %token <immval> IMMVAL
252 %token <immbool> IMMBOOL
254 %type <reg> dreg_name
255 %type <reg> dreg
256 %type <reg> sreg_name
257 %type <reg> relreg_name
258 %type <reg> sreg
259 %type <srcmod> smod
260 %type <writemask> writemask
261 %type <wm_components> wm_components
262 %type <swizzle> swizzle
263 %type <sw_components> sw_components
264 %type <modshift> omods
265 %type <modshift> omodifier
266 %type <comptype> comp
267 %type <declaration> dclusage
268 %type <reg> dcl_inputreg
269 %type <samplertype> sampdcl
270 %type <rel_reg> rel_reg
271 %type <reg> predicate
272 %type <immval> immsum
273 %type <sregs> sregs
277 shader: version_marker instructions
279 asm_ctx.funcs->end(&asm_ctx);
282 version_marker: VER_VS10
284 TRACE("Vertex shader 1.0\n");
285 create_vs10_parser(&asm_ctx);
287 | VER_VS11
289 TRACE("Vertex shader 1.1\n");
290 create_vs11_parser(&asm_ctx);
292 | VER_VS20
294 TRACE("Vertex shader 2.0\n");
295 create_vs20_parser(&asm_ctx);
297 | VER_VS2X
299 TRACE("Vertex shader 2.x\n");
300 create_vs2x_parser(&asm_ctx);
302 | VER_VS30
304 TRACE("Vertex shader 3.0\n");
305 create_vs30_parser(&asm_ctx);
307 | VER_PS10
309 TRACE("Pixel shader 1.0\n");
310 set_parse_status(&asm_ctx, PARSE_ERR);
311 YYABORT;
313 | VER_PS11
315 TRACE("Pixel shader 1.1\n");
316 set_parse_status(&asm_ctx, PARSE_ERR);
317 YYABORT;
319 | VER_PS12
321 TRACE("Pixel shader 1.2\n");
322 set_parse_status(&asm_ctx, PARSE_ERR);
323 YYABORT;
325 | VER_PS13
327 TRACE("Pixel shader 1.3\n");
328 set_parse_status(&asm_ctx, PARSE_ERR);
329 YYABORT;
331 | VER_PS14
333 TRACE("Pixel shader 1.4\n");
334 set_parse_status(&asm_ctx, PARSE_ERR);
335 YYABORT;
337 | VER_PS20
339 TRACE("Pixel shader 2.0\n");
340 create_ps20_parser(&asm_ctx);
342 | VER_PS2X
344 TRACE("Pixel shader 2.x\n");
345 create_ps2x_parser(&asm_ctx);
347 | VER_PS30
349 TRACE("Pixel shader 3.0\n");
350 create_ps30_parser(&asm_ctx);
353 instructions: /* empty */
354 | instructions complexinstr
356 /* Nothing to do */
359 complexinstr: instruction
363 | predicate instruction
365 TRACE("predicate\n");
366 asm_ctx.funcs->predicate(&asm_ctx, &$1);
369 instruction: INSTR_ADD omods dreg ',' sregs
371 TRACE("ADD\n");
372 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ADD, $2.mod, $2.shift, 0, &$3, &$5, 2);
374 | INSTR_NOP
376 TRACE("NOP\n");
377 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NOP, 0, 0, 0, 0, 0, 0);
379 | INSTR_MOV omods dreg ',' sregs
381 TRACE("MOV\n");
382 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOV, $2.mod, $2.shift, 0, &$3, &$5, 1);
384 | INSTR_SUB omods dreg ',' sregs
386 TRACE("SUB\n");
387 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SUB, $2.mod, $2.shift, 0, &$3, &$5, 2);
389 | INSTR_MAD omods dreg ',' sregs
391 TRACE("MAD\n");
392 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAD, $2.mod, $2.shift, 0, &$3, &$5, 3);
394 | INSTR_MUL omods dreg ',' sregs
396 TRACE("MUL\n");
397 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MUL, $2.mod, $2.shift, 0, &$3, &$5, 2);
399 | INSTR_RCP omods dreg ',' sregs
401 TRACE("RCP\n");
402 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RCP, $2.mod, $2.shift, 0, &$3, &$5, 1);
404 | INSTR_RSQ omods dreg ',' sregs
406 TRACE("RSQ\n");
407 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RSQ, $2.mod, $2.shift, 0, &$3, &$5, 1);
409 | INSTR_DP3 omods dreg ',' sregs
411 TRACE("DP3\n");
412 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP3, $2.mod, $2.shift, 0, &$3, &$5, 2);
414 | INSTR_DP4 omods dreg ',' sregs
416 TRACE("DP4\n");
417 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP4, $2.mod, $2.shift, 0, &$3, &$5, 2);
419 | INSTR_MIN omods dreg ',' sregs
421 TRACE("MIN\n");
422 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MIN, $2.mod, $2.shift, 0, &$3, &$5, 2);
424 | INSTR_MAX omods dreg ',' sregs
426 TRACE("MAX\n");
427 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAX, $2.mod, $2.shift, 0, &$3, &$5, 2);
429 | INSTR_SLT omods dreg ',' sregs
431 TRACE("SLT\n");
432 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SLT, $2.mod, $2.shift, 0, &$3, &$5, 2);
434 | INSTR_SGE omods dreg ',' sregs
436 TRACE("SGE\n");
437 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGE, $2.mod, $2.shift, 0, &$3, &$5, 2);
439 | INSTR_ABS omods dreg ',' sregs
441 TRACE("ABS\n");
442 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ABS, $2.mod, $2.shift, 0, &$3, &$5, 1);
444 | INSTR_EXP omods dreg ',' sregs
446 TRACE("EXP\n");
447 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXP, $2.mod, $2.shift, 0, &$3, &$5, 1);
449 | INSTR_LOG omods dreg ',' sregs
451 TRACE("LOG\n");
452 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOG, $2.mod, $2.shift, 0, &$3, &$5, 1);
454 | INSTR_LOGP omods dreg ',' sregs
456 TRACE("LOGP\n");
457 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOGP, $2.mod, $2.shift, 0, &$3, &$5, 1);
459 | INSTR_EXPP omods dreg ',' sregs
461 TRACE("EXPP\n");
462 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXPP, $2.mod, $2.shift, 0, &$3, &$5, 1);
464 | INSTR_DST omods dreg ',' sregs
466 TRACE("DST\n");
467 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DST, $2.mod, $2.shift, 0, &$3, &$5, 2);
469 | INSTR_LRP omods dreg ',' sregs
471 TRACE("LRP\n");
472 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LRP, $2.mod, $2.shift, 0, &$3, &$5, 3);
474 | INSTR_FRC omods dreg ',' sregs
476 TRACE("FRC\n");
477 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_FRC, $2.mod, $2.shift, 0, &$3, &$5, 1);
479 | INSTR_POW omods dreg ',' sregs
481 TRACE("POW\n");
482 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_POW, $2.mod, $2.shift, 0, &$3, &$5, 2);
484 | INSTR_CRS omods dreg ',' sregs
486 TRACE("CRS\n");
487 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CRS, $2.mod, $2.shift, 0, &$3, &$5, 2);
489 | INSTR_SGN omods dreg ',' sregs
491 TRACE("SGN\n");
492 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGN, $2.mod, $2.shift, 0, &$3, &$5, 3);
494 | INSTR_NRM omods dreg ',' sregs
496 TRACE("NRM\n");
497 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NRM, $2.mod, $2.shift, 0, &$3, &$5, 1);
499 | INSTR_SINCOS omods dreg ',' sregs
501 TRACE("SINCOS\n");
502 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SINCOS, $2.mod, $2.shift, 0, &$3, &$5, 1);
504 | INSTR_M4x4 omods dreg ',' sregs
506 TRACE("M4x4\n");
507 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
509 | INSTR_M4x3 omods dreg ',' sregs
511 TRACE("M4x3\n");
512 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
514 | INSTR_M3x4 omods dreg ',' sregs
516 TRACE("M3x4\n");
517 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
519 | INSTR_M3x3 omods dreg ',' sregs
521 TRACE("M3x3\n");
522 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
524 | INSTR_M3x2 omods dreg ',' sregs
526 TRACE("M3x2\n");
527 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x2, $2.mod, $2.shift, 0, &$3, &$5, 2);
529 | INSTR_DCL dclusage REG_OUTPUT
531 struct shader_reg reg;
532 TRACE("Output reg declaration\n");
533 ZeroMemory(&reg, sizeof(reg));
534 reg.type = BWRITERSPR_OUTPUT;
535 reg.regnum = $3;
536 reg.rel_reg = NULL;
537 reg.srcmod = 0;
538 reg.writemask = BWRITERSP_WRITEMASK_ALL;
539 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
541 | INSTR_DCL dclusage REG_OUTPUT writemask
543 struct shader_reg reg;
544 TRACE("Output reg declaration\n");
545 ZeroMemory(&reg, sizeof(reg));
546 reg.type = BWRITERSPR_OUTPUT;
547 reg.regnum = $3;
548 reg.rel_reg = NULL;
549 reg.srcmod = 0;
550 reg.writemask = $4;
551 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
553 | INSTR_DCL dclusage omods dcl_inputreg
555 struct shader_reg reg;
556 TRACE("Input reg declaration\n");
557 if($3.shift != 0) {
558 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
559 asm_ctx.line_no);
560 set_parse_status(&asm_ctx, PARSE_ERR);
562 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) ||
563 asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) {
564 asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n",
565 asm_ctx.line_no);
566 set_parse_status(&asm_ctx, PARSE_ERR);
568 ZeroMemory(&reg, sizeof(reg));
569 reg.type = $4.type;
570 reg.regnum = $4.regnum;
571 reg.rel_reg = NULL;
572 reg.srcmod = 0;
573 reg.writemask = BWRITERSP_WRITEMASK_ALL;
574 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, &reg);
576 | INSTR_DCL dclusage omods dcl_inputreg writemask
578 struct shader_reg reg;
579 TRACE("Input reg declaration\n");
580 if($3.shift != 0) {
581 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
582 asm_ctx.line_no);
583 set_parse_status(&asm_ctx, PARSE_ERR);
585 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) ||
586 asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) {
587 asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n",
588 asm_ctx.line_no);
589 set_parse_status(&asm_ctx, PARSE_ERR);
591 ZeroMemory(&reg, sizeof(reg));
592 reg.type = $4.type;
593 reg.regnum = $4.regnum;
594 reg.rel_reg = NULL;
595 reg.srcmod = 0;
596 reg.writemask = $5;
597 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, &reg);
599 | INSTR_DCL omods dcl_inputreg
601 struct shader_reg reg;
602 TRACE("Input reg declaration\n");
603 if($2.shift != 0) {
604 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
605 asm_ctx.line_no);
606 set_parse_status(&asm_ctx, PARSE_ERR);
608 if(asm_ctx.shader->type != ST_PIXEL) {
609 asmparser_message(&asm_ctx, "Line %u: Declaration needs a semantic\n",
610 asm_ctx.line_no);
611 set_parse_status(&asm_ctx, PARSE_ERR);
613 ZeroMemory(&reg, sizeof(reg));
614 reg.type = $3.type;
615 reg.regnum = $3.regnum;
616 reg.rel_reg = NULL;
617 reg.srcmod = 0;
618 reg.writemask = BWRITERSP_WRITEMASK_ALL;
619 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, &reg);
621 | INSTR_DCL omods dcl_inputreg writemask
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 = $4;
641 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, &reg);
643 | INSTR_DCL sampdcl omods REG_SAMPLER
645 TRACE("Sampler declared\n");
646 if($3.shift != 0) {
647 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
648 asm_ctx.line_no);
649 set_parse_status(&asm_ctx, PARSE_ERR);
651 asm_ctx.funcs->dcl_sampler(&asm_ctx, $2, $3.mod, $4, asm_ctx.line_no);
653 | INSTR_DCL omods REG_SAMPLER
655 TRACE("Sampler declared\n");
656 if($2.shift != 0) {
657 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
658 asm_ctx.line_no);
659 set_parse_status(&asm_ctx, PARSE_ERR);
661 if(asm_ctx.shader->type != ST_PIXEL) {
662 asmparser_message(&asm_ctx, "Line %u: Declaration needs a sampler type\n",
663 asm_ctx.line_no);
664 set_parse_status(&asm_ctx, PARSE_ERR);
666 asm_ctx.funcs->dcl_sampler(&asm_ctx, BWRITERSTT_UNKNOWN, $2.mod, $3, asm_ctx.line_no);
668 | INSTR_DCL sampdcl omods dcl_inputreg
670 TRACE("Error rule: sampler decl of input reg\n");
671 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of input regs is not valid\n",
672 asm_ctx.line_no);
673 set_parse_status(&asm_ctx, PARSE_WARN);
675 | INSTR_DCL sampdcl omods REG_OUTPUT
677 TRACE("Error rule: sampler decl of output reg\n");
678 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of output regs is not valid\n",
679 asm_ctx.line_no);
680 set_parse_status(&asm_ctx, PARSE_WARN);
682 | INSTR_DEF REG_CONSTFLOAT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
684 asm_ctx.funcs->constF(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val);
686 | INSTR_DEFI REG_CONSTINT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
688 asm_ctx.funcs->constI(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val);
690 | INSTR_DEFB REG_CONSTBOOL ',' IMMBOOL
692 asm_ctx.funcs->constB(&asm_ctx, $2, $4);
694 | INSTR_REP sregs
696 TRACE("REP\n");
697 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_REP, 0, 0, 0, 0, &$2, 1);
699 | INSTR_ENDREP
701 TRACE("ENDREP\n");
702 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDREP, 0, 0, 0, 0, 0, 0);
704 | INSTR_IF sregs
706 TRACE("IF\n");
707 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IF, 0, 0, 0, 0, &$2, 1);
709 | INSTR_IF comp sregs
711 TRACE("IFC\n");
712 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IFC, 0, 0, $2, 0, &$3, 2);
714 | INSTR_ELSE
716 TRACE("ELSE\n");
717 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ELSE, 0, 0, 0, 0, 0, 0);
719 | INSTR_ENDIF
721 TRACE("ENDIF\n");
722 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDIF, 0, 0, 0, 0, 0, 0);
724 | INSTR_BREAK
726 TRACE("BREAK\n");
727 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAK, 0, 0, 0, 0, 0, 0);
729 | INSTR_BREAK comp sregs
731 TRACE("BREAKC\n");
732 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKC, 0, 0, $2, 0, &$3, 2);
734 | INSTR_BREAKP sregs
736 TRACE("BREAKP\n");
737 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKP, 0, 0, 0, 0, &$2, 1);
739 | INSTR_CALL sregs
741 TRACE("CALL\n");
742 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALL, 0, 0, 0, 0, &$2, 1);
744 | INSTR_CALLNZ sregs
746 TRACE("CALLNZ\n");
747 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALLNZ, 0, 0, 0, 0, &$2, 2);
749 | INSTR_LOOP sregs
751 TRACE("LOOP\n");
752 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOOP, 0, 0, 0, 0, &$2, 2);
754 | INSTR_RET
756 TRACE("RET\n");
757 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RET, 0, 0, 0, 0, 0, 0);
759 | INSTR_ENDLOOP
761 TRACE("ENDLOOP\n");
762 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDLOOP, 0, 0, 0, 0, 0, 0);
764 | INSTR_LABEL sregs
766 TRACE("LABEL\n");
767 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LABEL, 0, 0, 0, 0, &$2, 1);
769 | INSTR_SETP comp dreg ',' sregs
771 TRACE("SETP\n");
772 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SETP, 0, 0, $2, &$3, &$5, 2);
774 | INSTR_TEXLDL omods dreg ',' sregs
776 TRACE("TEXLDL\n");
777 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDL, $2.mod, $2.shift, 0, &$3, &$5, 2);
779 | INSTR_LIT omods dreg ',' sregs
781 TRACE("LIT\n");
782 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LIT, $2.mod, $2.shift, 0, &$3, &$5, 1);
784 | INSTR_MOVA omods dreg ',' sregs
786 TRACE("MOVA\n");
787 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOVA, $2.mod, $2.shift, 0, &$3, &$5, 1);
789 | INSTR_CMP omods dreg ',' sregs
791 TRACE("CMP\n");
792 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CMP, $2.mod, $2.shift, 0, &$3, &$5, 3);
794 | INSTR_DP2ADD omods dreg ',' sregs
796 TRACE("DP2ADD\n");
797 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP2ADD, $2.mod, $2.shift, 0, &$3, &$5, 3);
799 | INSTR_TEXKILL dreg
801 TRACE("TEXKILL\n");
802 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXKILL, 0, 0, 0, &$2, 0, 0);
804 | INSTR_TEXLD omods dreg ',' sregs
806 TRACE("TEXLD\n");
807 /* There is more than one acceptable syntax for texld:
808 with 1 sreg (PS 1.4) or
809 with 2 sregs (PS 2.0+)
810 Moreover, texld shares the same opcode as the tex instruction,
811 so there are a total of 3 valid syntaxes
812 These variations are handled in asmparser.c */
813 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, &$5, 2);
815 | INSTR_TEXLDP omods dreg ',' sregs
817 TRACE("TEXLDP\n");
818 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDP, $2.mod, $2.shift, 0, &$3, &$5, 2);
820 | INSTR_TEXLDB omods dreg ',' sregs
822 TRACE("TEXLDB\n");
823 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDB, $2.mod, $2.shift, 0, &$3, &$5, 2);
825 | INSTR_DSX omods dreg ',' sregs
827 TRACE("DSX\n");
828 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSX, $2.mod, $2.shift, 0, &$3, &$5, 1);
830 | INSTR_DSY omods dreg ',' sregs
832 TRACE("DSY\n");
833 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSY, $2.mod, $2.shift, 0, &$3, &$5, 1);
835 | INSTR_TEXLDD omods dreg ',' sregs
837 TRACE("TEXLDD\n");
838 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDD, $2.mod, $2.shift, 0, &$3, &$5, 4);
841 dreg: dreg_name rel_reg
843 $$.regnum = $1.regnum;
844 $$.type = $1.type;
845 $$.writemask = BWRITERSP_WRITEMASK_ALL;
846 $$.srcmod = BWRITERSPSM_NONE;
847 set_rel_reg(&$$, &$2);
849 | dreg_name writemask
851 $$.regnum = $1.regnum;
852 $$.type = $1.type;
853 $$.writemask = $2;
854 $$.srcmod = BWRITERSPSM_NONE;
855 $$.rel_reg = NULL;
858 dreg_name: REG_TEMP
860 $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
862 | REG_OUTPUT
864 $$.regnum = $1; $$.type = BWRITERSPR_OUTPUT;
866 | REG_INPUT
868 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
870 | REG_CONSTFLOAT
872 asmparser_message(&asm_ctx, "Line %u: Register c%u is not a valid destination register\n",
873 asm_ctx.line_no, $1);
874 set_parse_status(&asm_ctx, PARSE_WARN);
876 | REG_CONSTINT
878 asmparser_message(&asm_ctx, "Line %u: Register i%u is not a valid destination register\n",
879 asm_ctx.line_no, $1);
880 set_parse_status(&asm_ctx, PARSE_WARN);
882 | REG_CONSTBOOL
884 asmparser_message(&asm_ctx, "Line %u: Register b%u is not a valid destination register\n",
885 asm_ctx.line_no, $1);
886 set_parse_status(&asm_ctx, PARSE_WARN);
888 | REG_TEXTURE
890 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
892 | REG_TEXCRDOUT
894 $$.regnum = $1; $$.type = BWRITERSPR_TEXCRDOUT;
896 | REG_SAMPLER
898 asmparser_message(&asm_ctx, "Line %u: Register s%u is not a valid destination register\n",
899 asm_ctx.line_no, $1);
900 set_parse_status(&asm_ctx, PARSE_WARN);
902 | REG_OPOS
904 $$.regnum = BWRITERSRO_POSITION; $$.type = BWRITERSPR_RASTOUT;
906 | REG_OPTS
908 $$.regnum = BWRITERSRO_POINT_SIZE; $$.type = BWRITERSPR_RASTOUT;
910 | REG_OFOG
912 $$.regnum = BWRITERSRO_FOG; $$.type = BWRITERSPR_RASTOUT;
914 | REG_VERTEXCOLOR
916 $$.regnum = $1; $$.type = BWRITERSPR_ATTROUT;
918 | REG_FRAGCOLOR
920 $$.regnum = $1; $$.type = BWRITERSPR_COLOROUT;
922 | REG_FRAGDEPTH
924 $$.regnum = 0; $$.type = BWRITERSPR_DEPTHOUT;
926 | REG_PREDICATE
928 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
930 | REG_VPOS
932 asmparser_message(&asm_ctx, "Line %u: Register vPos is not a valid destination register\n",
933 asm_ctx.line_no);
934 set_parse_status(&asm_ctx, PARSE_WARN);
936 | REG_VFACE
938 asmparser_message(&asm_ctx, "Line %u: Register vFace is not a valid destination register\n",
939 asm_ctx.line_no);
940 set_parse_status(&asm_ctx, PARSE_WARN);
942 | REG_ADDRESS
944 /* index 0 is hardcoded for the addr register */
945 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
947 | REG_LOOP
949 asmparser_message(&asm_ctx, "Line %u: Register aL is not a valid destination register\n",
950 asm_ctx.line_no);
951 set_parse_status(&asm_ctx, PARSE_WARN);
954 writemask: '.' wm_components
956 if($2.writemask == SWIZZLE_ERR) {
957 asmparser_message(&asm_ctx, "Line %u: Invalid writemask specified\n",
958 asm_ctx.line_no);
959 set_parse_status(&asm_ctx, PARSE_ERR);
960 /* Provide a correct writemask to prevent following complaints */
961 $$ = BWRITERSP_WRITEMASK_ALL;
963 else {
964 $$ = $2.writemask;
965 TRACE("Writemask: %x\n", $$);
969 wm_components: COMPONENT
971 $$.writemask = 1 << $1;
972 $$.last = $1;
973 $$.idx = 1;
975 | wm_components COMPONENT
977 if($1.writemask == SWIZZLE_ERR || $1.idx == 4)
978 /* Wrong writemask */
979 $$.writemask = SWIZZLE_ERR;
980 else {
981 if($2 <= $1.last)
982 $$.writemask = SWIZZLE_ERR;
983 else {
984 $$.writemask = $1.writemask | (1 << $2);
985 $$.idx = $1.idx + 1;
990 swizzle: /* empty */
992 $$ = BWRITERVS_NOSWIZZLE;
993 TRACE("Default swizzle: %08x\n", $$);
995 | '.' sw_components
997 if($2.swizzle == SWIZZLE_ERR) {
998 asmparser_message(&asm_ctx, "Line %u: Invalid swizzle\n",
999 asm_ctx.line_no);
1000 set_parse_status(&asm_ctx, PARSE_ERR);
1001 /* Provide a correct swizzle to prevent following complaints */
1002 $$ = BWRITERVS_NOSWIZZLE;
1004 else {
1005 DWORD last, i;
1007 $$ = $2.swizzle << BWRITERVS_SWIZZLE_SHIFT;
1008 /* Fill the swizzle by extending the last component */
1009 last = ($2.swizzle >> 2 * ($2.idx - 1)) & 0x03;
1010 for(i = $2.idx; i < 4; i++){
1011 $$ |= last << (BWRITERVS_SWIZZLE_SHIFT + 2 * i);
1013 TRACE("Got a swizzle: %08x\n", $$);
1017 sw_components: COMPONENT
1019 $$.swizzle = $1;
1020 $$.idx = 1;
1022 | sw_components COMPONENT
1024 if($1.idx == 4) {
1025 /* Too many sw_components */
1026 $$.swizzle = SWIZZLE_ERR;
1027 $$.idx = 4;
1029 else {
1030 $$.swizzle = $1.swizzle | ($2 << 2 * $1.idx);
1031 $$.idx = $1.idx + 1;
1035 omods: /* Empty */
1037 $$.mod = 0;
1038 $$.shift = 0;
1040 | omods omodifier
1042 $$.mod = $1.mod | $2.mod;
1043 if($1.shift && $2.shift) {
1044 asmparser_message(&asm_ctx, "Line %u: More than one shift flag\n",
1045 asm_ctx.line_no);
1046 set_parse_status(&asm_ctx, PARSE_ERR);
1047 $$.shift = $1.shift;
1048 } else {
1049 $$.shift = $1.shift | $2.shift;
1053 omodifier: SHIFT_X2
1055 $$.mod = 0;
1056 $$.shift = 1;
1058 | SHIFT_X4
1060 $$.mod = 0;
1061 $$.shift = 2;
1063 | SHIFT_X8
1065 $$.mod = 0;
1066 $$.shift = 3;
1068 | SHIFT_D2
1070 $$.mod = 0;
1071 $$.shift = 15;
1073 | SHIFT_D4
1075 $$.mod = 0;
1076 $$.shift = 14;
1078 | SHIFT_D8
1080 $$.mod = 0;
1081 $$.shift = 13;
1083 | MOD_SAT
1085 $$.mod = BWRITERSPDM_SATURATE;
1086 $$.shift = 0;
1088 | MOD_PP
1090 $$.mod = BWRITERSPDM_PARTIALPRECISION;
1091 $$.shift = 0;
1093 | MOD_CENTROID
1095 $$.mod = BWRITERSPDM_MSAMPCENTROID;
1096 $$.shift = 0;
1099 sregs: sreg
1101 $$.reg[0] = $1;
1102 $$.count = 1;
1104 | sregs ',' sreg
1106 if($$.count == MAX_SRC_REGS){
1107 asmparser_message(&asm_ctx, "Line %u: Too many source registers in this instruction\n",
1108 asm_ctx.line_no);
1109 set_parse_status(&asm_ctx, PARSE_ERR);
1111 else
1112 $$.reg[$$.count++] = $3;
1115 sreg: sreg_name rel_reg swizzle
1117 $$.type = $1.type;
1118 $$.regnum = $1.regnum;
1119 $$.swizzle = $3;
1120 $$.srcmod = BWRITERSPSM_NONE;
1121 set_rel_reg(&$$, &$2);
1123 | sreg_name rel_reg smod swizzle
1125 $$.type = $1.type;
1126 $$.regnum = $1.regnum;
1127 set_rel_reg(&$$, &$2);
1128 $$.srcmod = $3;
1129 $$.swizzle = $4;
1131 | '-' sreg_name rel_reg swizzle
1133 $$.type = $2.type;
1134 $$.regnum = $2.regnum;
1135 $$.srcmod = BWRITERSPSM_NEG;
1136 set_rel_reg(&$$, &$3);
1137 $$.swizzle = $4;
1139 | '-' sreg_name rel_reg smod swizzle
1141 $$.type = $2.type;
1142 $$.regnum = $2.regnum;
1143 set_rel_reg(&$$, &$3);
1144 switch($4) {
1145 case BWRITERSPSM_BIAS: $$.srcmod = BWRITERSPSM_BIASNEG; break;
1146 case BWRITERSPSM_X2: $$.srcmod = BWRITERSPSM_X2NEG; break;
1147 case BWRITERSPSM_SIGN: $$.srcmod = BWRITERSPSM_SIGNNEG; break;
1148 case BWRITERSPSM_ABS: $$.srcmod = BWRITERSPSM_ABSNEG; break;
1149 case BWRITERSPSM_DZ:
1150 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DZ\n",
1151 asm_ctx.line_no);
1152 set_parse_status(&asm_ctx, PARSE_ERR);
1153 break;
1154 case BWRITERSPSM_DW:
1155 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DW\n",
1156 asm_ctx.line_no);
1157 set_parse_status(&asm_ctx, PARSE_ERR);
1158 break;
1159 default:
1160 FIXME("Unhandled combination of NEGATE and %u\n", $4);
1162 $$.swizzle = $5;
1164 | IMMVAL '-' sreg_name rel_reg swizzle
1166 if($1.val != 1.0 || (!$1.integer)) {
1167 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP, "
1168 "%g - reg found\n", asm_ctx.line_no, $1.val);
1169 set_parse_status(&asm_ctx, PARSE_ERR);
1171 /* Complement - not compatible with other source modifiers */
1172 $$.type = $3.type;
1173 $$.regnum = $3.regnum;
1174 $$.srcmod = BWRITERSPSM_COMP;
1175 set_rel_reg(&$$, &$4);
1176 $$.swizzle = $5;
1178 | IMMVAL '-' sreg_name rel_reg smod swizzle
1180 /* For nicer error reporting */
1181 if($1.val != 1.0 || (!$1.integer)) {
1182 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP\n",
1183 asm_ctx.line_no);
1184 set_parse_status(&asm_ctx, PARSE_ERR);
1185 } else {
1186 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: D3DSPSM_COMP and %s\n",
1187 asm_ctx.line_no,
1188 debug_print_srcmod($5));
1189 set_parse_status(&asm_ctx, PARSE_ERR);
1192 | SMOD_NOT sreg_name swizzle
1194 $$.type = $2.type;
1195 $$.regnum = $2.regnum;
1196 $$.rel_reg = NULL;
1197 $$.srcmod = BWRITERSPSM_NOT;
1198 $$.swizzle = $3;
1201 rel_reg: /* empty */
1203 $$.has_rel_reg = FALSE;
1204 $$.additional_offset = 0;
1206 | '[' immsum ']'
1208 $$.has_rel_reg = FALSE;
1209 $$.additional_offset = $2.val;
1211 | '[' relreg_name swizzle ']'
1213 $$.has_rel_reg = TRUE;
1214 $$.type = $2.type;
1215 $$.additional_offset = 0;
1216 $$.rel_regnum = $2.regnum;
1217 $$.swizzle = $3;
1219 | '[' immsum '+' relreg_name swizzle ']'
1221 $$.has_rel_reg = TRUE;
1222 $$.type = $4.type;
1223 $$.additional_offset = $2.val;
1224 $$.rel_regnum = $4.regnum;
1225 $$.swizzle = $5;
1227 | '[' relreg_name swizzle '+' immsum ']'
1229 $$.has_rel_reg = TRUE;
1230 $$.type = $2.type;
1231 $$.additional_offset = $5.val;
1232 $$.rel_regnum = $2.regnum;
1233 $$.swizzle = $3;
1235 | '[' immsum '+' relreg_name swizzle '+' immsum ']'
1237 $$.has_rel_reg = TRUE;
1238 $$.type = $4.type;
1239 $$.additional_offset = $2.val + $7.val;
1240 $$.rel_regnum = $4.regnum;
1241 $$.swizzle = $5;
1244 immsum: IMMVAL
1246 if(!$1.integer) {
1247 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1248 asm_ctx.line_no, $1.val);
1249 set_parse_status(&asm_ctx, PARSE_ERR);
1251 $$.val = $1.val;
1253 | immsum '+' IMMVAL
1255 if(!$3.integer) {
1256 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1257 asm_ctx.line_no, $3.val);
1258 set_parse_status(&asm_ctx, PARSE_ERR);
1260 $$.val = $1.val + $3.val;
1263 smod: SMOD_BIAS
1265 $$ = BWRITERSPSM_BIAS;
1267 | SHIFT_X2
1269 $$ = BWRITERSPSM_X2;
1271 | SMOD_SCALEBIAS
1273 $$ = BWRITERSPSM_SIGN;
1275 | SMOD_DZ
1277 $$ = BWRITERSPSM_DZ;
1279 | SMOD_DW
1281 $$ = BWRITERSPSM_DW;
1283 | SMOD_ABS
1285 $$ = BWRITERSPSM_ABS;
1288 relreg_name: REG_ADDRESS
1290 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1292 | REG_LOOP
1294 $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1297 sreg_name: REG_TEMP
1299 $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
1301 | REG_OUTPUT
1303 asmparser_message(&asm_ctx, "Line %u: Register o%u is not a valid source register\n",
1304 asm_ctx.line_no, $1);
1305 set_parse_status(&asm_ctx, PARSE_WARN);
1307 | REG_INPUT
1309 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1311 | REG_CONSTFLOAT
1313 $$.regnum = $1; $$.type = BWRITERSPR_CONST;
1315 | REG_CONSTINT
1317 $$.regnum = $1; $$.type = BWRITERSPR_CONSTINT;
1319 | REG_CONSTBOOL
1321 $$.regnum = $1; $$.type = BWRITERSPR_CONSTBOOL;
1323 | REG_TEXTURE
1325 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1327 | REG_TEXCRDOUT
1329 asmparser_message(&asm_ctx, "Line %u: Register oT%u is not a valid source register\n",
1330 asm_ctx.line_no, $1);
1331 set_parse_status(&asm_ctx, PARSE_WARN);
1333 | REG_SAMPLER
1335 $$.regnum = $1; $$.type = BWRITERSPR_SAMPLER;
1337 | REG_OPOS
1339 asmparser_message(&asm_ctx, "Line %u: Register oPos is not a valid source register\n",
1340 asm_ctx.line_no);
1341 set_parse_status(&asm_ctx, PARSE_WARN);
1343 | REG_OFOG
1345 asmparser_message(&asm_ctx, "Line %u: Register oFog is not a valid source register\n",
1346 asm_ctx.line_no);
1347 set_parse_status(&asm_ctx, PARSE_WARN);
1349 | REG_VERTEXCOLOR
1351 asmparser_message(&asm_ctx, "Line %u: Register oD%u is not a valid source register\n",
1352 asm_ctx.line_no, $1);
1353 set_parse_status(&asm_ctx, PARSE_WARN);
1355 | REG_FRAGCOLOR
1357 asmparser_message(&asm_ctx, "Line %u: Register oC%u is not a valid source register\n",
1358 asm_ctx.line_no, $1);
1359 set_parse_status(&asm_ctx, PARSE_WARN);
1361 | REG_FRAGDEPTH
1363 asmparser_message(&asm_ctx, "Line %u: Register oDepth is not a valid source register\n",
1364 asm_ctx.line_no);
1365 set_parse_status(&asm_ctx, PARSE_WARN);
1367 | REG_PREDICATE
1369 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
1371 | REG_VPOS
1373 $$.regnum = 0; $$.type = BWRITERSPR_MISCTYPE;
1375 | REG_VFACE
1377 $$.regnum = 1; $$.type = BWRITERSPR_MISCTYPE;
1379 | REG_ADDRESS
1381 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1383 | REG_LOOP
1385 $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1387 | REG_LABEL
1389 $$.regnum = $1; $$.type = BWRITERSPR_LABEL;
1392 comp: COMP_GT { $$ = BWRITER_COMPARISON_GT; }
1393 | COMP_LT { $$ = BWRITER_COMPARISON_LT; }
1394 | COMP_GE { $$ = BWRITER_COMPARISON_GE; }
1395 | COMP_LE { $$ = BWRITER_COMPARISON_LE; }
1396 | COMP_EQ { $$ = BWRITER_COMPARISON_EQ; }
1397 | COMP_NE { $$ = BWRITER_COMPARISON_NE; }
1399 dclusage: USAGE_POSITION
1401 TRACE("dcl_position%u\n", $1);
1402 $$.regnum = $1;
1403 $$.dclusage = BWRITERDECLUSAGE_POSITION;
1405 | USAGE_BLENDWEIGHT
1407 TRACE("dcl_blendweight%u\n", $1);
1408 $$.regnum = $1;
1409 $$.dclusage = BWRITERDECLUSAGE_BLENDWEIGHT;
1411 | USAGE_BLENDINDICES
1413 TRACE("dcl_blendindices%u\n", $1);
1414 $$.regnum = $1;
1415 $$.dclusage = BWRITERDECLUSAGE_BLENDINDICES;
1417 | USAGE_NORMAL
1419 TRACE("dcl_normal%u\n", $1);
1420 $$.regnum = $1;
1421 $$.dclusage = BWRITERDECLUSAGE_NORMAL;
1423 | USAGE_PSIZE
1425 TRACE("dcl_psize%u\n", $1);
1426 $$.regnum = $1;
1427 $$.dclusage = BWRITERDECLUSAGE_PSIZE;
1429 | USAGE_TEXCOORD
1431 TRACE("dcl_texcoord%u\n", $1);
1432 $$.regnum = $1;
1433 $$.dclusage = BWRITERDECLUSAGE_TEXCOORD;
1435 | USAGE_TANGENT
1437 TRACE("dcl_tangent%u\n", $1);
1438 $$.regnum = $1;
1439 $$.dclusage = BWRITERDECLUSAGE_TANGENT;
1441 | USAGE_BINORMAL
1443 TRACE("dcl_binormal%u\n", $1);
1444 $$.regnum = $1;
1445 $$.dclusage = BWRITERDECLUSAGE_BINORMAL;
1447 | USAGE_TESSFACTOR
1449 TRACE("dcl_tessfactor%u\n", $1);
1450 $$.regnum = $1;
1451 $$.dclusage = BWRITERDECLUSAGE_TESSFACTOR;
1453 | USAGE_POSITIONT
1455 TRACE("dcl_positiont%u\n", $1);
1456 $$.regnum = $1;
1457 $$.dclusage = BWRITERDECLUSAGE_POSITIONT;
1459 | USAGE_COLOR
1461 TRACE("dcl_color%u\n", $1);
1462 $$.regnum = $1;
1463 $$.dclusage = BWRITERDECLUSAGE_COLOR;
1465 | USAGE_FOG
1467 TRACE("dcl_fog%u\n", $1);
1468 $$.regnum = $1;
1469 $$.dclusage = BWRITERDECLUSAGE_FOG;
1471 | USAGE_DEPTH
1473 TRACE("dcl_depth%u\n", $1);
1474 $$.regnum = $1;
1475 $$.dclusage = BWRITERDECLUSAGE_DEPTH;
1477 | USAGE_SAMPLE
1479 TRACE("dcl_sample%u\n", $1);
1480 $$.regnum = $1;
1481 $$.dclusage = BWRITERDECLUSAGE_SAMPLE;
1484 dcl_inputreg: REG_INPUT
1486 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1488 | REG_TEXTURE
1490 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1493 sampdcl: SAMPTYPE_1D
1495 $$ = BWRITERSTT_1D;
1497 | SAMPTYPE_2D
1499 $$ = BWRITERSTT_2D;
1501 | SAMPTYPE_CUBE
1503 $$ = BWRITERSTT_CUBE;
1505 | SAMPTYPE_VOLUME
1507 $$ = BWRITERSTT_VOLUME;
1510 predicate: '(' REG_PREDICATE swizzle ')'
1512 $$.type = BWRITERSPR_PREDICATE;
1513 $$.regnum = 0;
1514 $$.rel_reg = NULL;
1515 $$.srcmod = BWRITERSPSM_NONE;
1516 $$.swizzle = $3;
1518 | '(' SMOD_NOT REG_PREDICATE swizzle ')'
1520 $$.type = BWRITERSPR_PREDICATE;
1521 $$.regnum = 0;
1522 $$.rel_reg = NULL;
1523 $$.srcmod = BWRITERSPSM_NOT;
1524 $$.swizzle = $4;
1529 void asmshader_error (char const *s) {
1530 asmparser_message(&asm_ctx, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no, s);
1531 set_parse_status(&asm_ctx, PARSE_ERR);
1534 /* Error reporting function */
1535 void asmparser_message(struct asm_parser *ctx, const char *fmt, ...) {
1536 va_list args;
1537 char* newbuffer;
1538 int rc, newsize;
1540 if(ctx->messagecapacity == 0) {
1541 ctx->messages = asm_alloc(MESSAGEBUFFER_INITIAL_SIZE);
1542 if(ctx->messages == NULL) {
1543 ERR("Error allocating memory for parser messages\n");
1544 return;
1546 ctx->messagecapacity = MESSAGEBUFFER_INITIAL_SIZE;
1549 while(1) {
1550 va_start(args, fmt);
1551 rc = vsnprintf(ctx->messages + ctx->messagesize,
1552 ctx->messagecapacity - ctx->messagesize, fmt, args);
1553 va_end(args);
1555 if (rc < 0 || /* C89 */
1556 rc >= ctx->messagecapacity - ctx->messagesize) { /* C99 */
1557 /* Resize the buffer */
1558 newsize = ctx->messagecapacity * 2;
1559 newbuffer = asm_realloc(ctx->messages, newsize);
1560 if(newbuffer == NULL){
1561 ERR("Error reallocating memory for parser messages\n");
1562 return;
1564 ctx->messages = newbuffer;
1565 ctx->messagecapacity = newsize;
1566 } else {
1567 ctx->messagesize += rc;
1568 return;
1573 /* New status is the worst between current status and parameter value */
1574 void set_parse_status(struct asm_parser *ctx, enum parse_status status) {
1575 if(status == PARSE_ERR) ctx->status = PARSE_ERR;
1576 else if(status == PARSE_WARN && ctx->status == PARSE_SUCCESS) ctx->status = PARSE_WARN;
1579 struct bwriter_shader *parse_asm_shader(char **messages) {
1580 struct bwriter_shader *ret = NULL;
1582 asm_ctx.shader = NULL;
1583 asm_ctx.status = PARSE_SUCCESS;
1584 asm_ctx.messagesize = asm_ctx.messagecapacity = 0;
1585 asm_ctx.line_no = 1;
1587 asmshader_parse();
1589 if(asm_ctx.status != PARSE_ERR) ret = asm_ctx.shader;
1590 else if(asm_ctx.shader) SlDeleteShader(asm_ctx.shader);
1592 if(messages) {
1593 if(asm_ctx.messagesize) {
1594 /* Shrink the buffer to the used size */
1595 *messages = asm_realloc(asm_ctx.messages, asm_ctx.messagesize + 1);
1596 if(!*messages) {
1597 ERR("Out of memory, no messages reported\n");
1598 asm_free(asm_ctx.messages);
1600 } else {
1601 *messages = NULL;
1603 } else {
1604 if(asm_ctx.messagecapacity) asm_free(asm_ctx.messages);
1607 return ret;