d3dx9: Add sampler dcl instruction support to the shader assembler.
[wine.git] / dlls / d3dx9_36 / asmshader.y
bloba6ab57e9db205b561aa21d81b2f43ec8f837fd5d
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 unsigned int regnum;
64 struct shader_reg reg;
65 DWORD srcmod;
66 DWORD writemask;
67 struct {
68 DWORD writemask;
69 DWORD idx;
70 DWORD last;
71 } wm_components;
72 DWORD swizzle;
73 struct {
74 DWORD swizzle;
75 DWORD idx;
76 } sw_components;
77 DWORD component;
78 struct {
79 DWORD mod;
80 DWORD shift;
81 } modshift;
82 BWRITER_COMPARISON_TYPE comptype;
83 struct {
84 DWORD dclusage;
85 unsigned int regnum;
86 } declaration;
87 BWRITERSAMPLER_TEXTURE_TYPE samplertype;
88 struct rel_reg rel_reg;
89 struct src_regs sregs;
92 /* Common instructions between vertex and pixel shaders */
93 %token INSTR_ADD
94 %token INSTR_NOP
95 %token INSTR_MOV
96 %token INSTR_SUB
97 %token INSTR_MAD
98 %token INSTR_MUL
99 %token INSTR_RCP
100 %token INSTR_RSQ
101 %token INSTR_DP3
102 %token INSTR_DP4
103 %token INSTR_MIN
104 %token INSTR_MAX
105 %token INSTR_SLT
106 %token INSTR_SGE
107 %token INSTR_ABS
108 %token INSTR_EXP
109 %token INSTR_LOG
110 %token INSTR_EXPP
111 %token INSTR_LOGP
112 %token INSTR_DST
113 %token INSTR_LRP
114 %token INSTR_FRC
115 %token INSTR_POW
116 %token INSTR_CRS
117 %token INSTR_SGN
118 %token INSTR_NRM
119 %token INSTR_SINCOS
120 %token INSTR_M4x4
121 %token INSTR_M4x3
122 %token INSTR_M3x4
123 %token INSTR_M3x3
124 %token INSTR_M3x2
125 %token INSTR_DCL
126 %token INSTR_REP
127 %token INSTR_ENDREP
128 %token INSTR_IF
129 %token INSTR_ELSE
130 %token INSTR_ENDIF
131 %token INSTR_BREAK
132 %token INSTR_BREAKP
133 %token INSTR_CALL
134 %token INSTR_CALLNZ
135 %token INSTR_LOOP
136 %token INSTR_RET
137 %token INSTR_ENDLOOP
138 %token INSTR_LABEL
139 %token INSTR_SETP
140 %token INSTR_TEXLDL
142 /* Vertex shader only instructions */
143 %token INSTR_LIT
144 %token INSTR_MOVA
146 /* Registers */
147 %token <regnum> REG_TEMP
148 %token <regnum> REG_OUTPUT
149 %token <regnum> REG_INPUT
150 %token <regnum> REG_CONSTFLOAT
151 %token <regnum> REG_CONSTINT
152 %token <regnum> REG_CONSTBOOL
153 %token <regnum> REG_TEXTURE
154 %token <regnum> REG_SAMPLER
155 %token <regnum> REG_TEXCRDOUT
156 %token REG_OPOS
157 %token REG_OFOG
158 %token REG_OPTS
159 %token <regnum> REG_VERTEXCOLOR
160 %token <regnum> REG_FRAGCOLOR
161 %token REG_FRAGDEPTH
162 %token REG_VPOS
163 %token REG_VFACE
164 %token REG_ADDRESS
165 %token REG_LOOP
166 %token REG_PREDICATE
167 %token <regnum> REG_LABEL
169 /* Version tokens */
170 %token VER_VS10
171 %token VER_VS11
172 %token VER_VS20
173 %token VER_VS2X
174 %token VER_VS30
176 %token VER_PS10
177 %token VER_PS11
178 %token VER_PS12
179 %token VER_PS13
180 %token VER_PS14
181 %token VER_PS20
182 %token VER_PS2X
183 %token VER_PS30
185 /* Output modifiers */
186 %token MOD_SAT
187 %token MOD_PP
188 %token MOD_CENTROID
190 /* Compare tokens */
191 %token COMP_GT
192 %token COMP_LT
193 %token COMP_GE
194 %token COMP_LE
195 %token COMP_EQ
196 %token COMP_NE
198 /* Source register modifiers */
199 %token SMOD_ABS
200 %token SMOD_NOT
202 /* Sampler types */
203 %token SAMPTYPE_1D
204 %token SAMPTYPE_2D
205 %token SAMPTYPE_CUBE
206 %token SAMPTYPE_VOLUME
208 /* Usage declaration tokens */
209 %token <regnum> USAGE_POSITION
210 %token <regnum> USAGE_BLENDWEIGHT
211 %token <regnum> USAGE_BLENDINDICES
212 %token <regnum> USAGE_NORMAL
213 %token <regnum> USAGE_PSIZE
214 %token <regnum> USAGE_TEXCOORD
215 %token <regnum> USAGE_TANGENT
216 %token <regnum> USAGE_BINORMAL
217 %token <regnum> USAGE_TESSFACTOR
218 %token <regnum> USAGE_POSITIONT
219 %token <regnum> USAGE_COLOR
220 %token <regnum> USAGE_FOG
221 %token <regnum> USAGE_DEPTH
222 %token <regnum> USAGE_SAMPLE
224 /* Misc stuff */
225 %token <component> COMPONENT
226 %token <immval> IMMVAL
228 %type <reg> dreg_name
229 %type <reg> dreg
230 %type <reg> sreg_name
231 %type <reg> relreg_name
232 %type <reg> sreg
233 %type <srcmod> smod
234 %type <writemask> writemask
235 %type <wm_components> wm_components
236 %type <swizzle> swizzle
237 %type <sw_components> sw_components
238 %type <modshift> omods
239 %type <modshift> omodifier
240 %type <comptype> comp
241 %type <declaration> dclusage
242 %type <samplertype> sampdcl
243 %type <rel_reg> rel_reg
244 %type <reg> predicate
245 %type <immval> immsum
246 %type <sregs> sregs
250 shader: version_marker instructions
252 asm_ctx.funcs->end(&asm_ctx);
255 version_marker: VER_VS10
257 TRACE("Vertex shader 1.0\n");
258 set_parse_status(&asm_ctx, PARSE_ERR);
259 YYABORT;
261 | VER_VS11
263 TRACE("Vertex shader 1.1\n");
264 set_parse_status(&asm_ctx, PARSE_ERR);
265 YYABORT;
267 | VER_VS20
269 TRACE("Vertex shader 2.0\n");
270 set_parse_status(&asm_ctx, PARSE_ERR);
271 YYABORT;
273 | VER_VS2X
275 TRACE("Vertex shader 2.x\n");
276 set_parse_status(&asm_ctx, PARSE_ERR);
277 YYABORT;
279 | VER_VS30
281 TRACE("Vertex shader 3.0\n");
282 create_vs30_parser(&asm_ctx);
284 | VER_PS10
286 TRACE("Pixel shader 1.0\n");
287 set_parse_status(&asm_ctx, PARSE_ERR);
288 YYABORT;
290 | VER_PS11
292 TRACE("Pixel shader 1.1\n");
293 set_parse_status(&asm_ctx, PARSE_ERR);
294 YYABORT;
296 | VER_PS12
298 TRACE("Pixel shader 1.2\n");
299 set_parse_status(&asm_ctx, PARSE_ERR);
300 YYABORT;
302 | VER_PS13
304 TRACE("Pixel shader 1.3\n");
305 set_parse_status(&asm_ctx, PARSE_ERR);
306 YYABORT;
308 | VER_PS14
310 TRACE("Pixel shader 1.4\n");
311 set_parse_status(&asm_ctx, PARSE_ERR);
312 YYABORT;
314 | VER_PS20
316 TRACE("Pixel shader 2.0\n");
317 set_parse_status(&asm_ctx, PARSE_ERR);
318 YYABORT;
320 | VER_PS2X
322 TRACE("Pixel shader 2.x\n");
323 set_parse_status(&asm_ctx, PARSE_ERR);
324 YYABORT;
326 | VER_PS30
328 TRACE("Pixel shader 3.0\n");
329 set_parse_status(&asm_ctx, PARSE_ERR);
330 YYABORT;
333 instructions: /* empty */
334 | instructions complexinstr
336 /* Nothing to do */
339 complexinstr: instruction
343 | predicate instruction
345 TRACE("predicate\n");
346 asm_ctx.funcs->predicate(&asm_ctx, &$1);
349 instruction: INSTR_ADD omods dreg ',' sregs
351 TRACE("ADD\n");
352 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ADD, $2.mod, $2.shift, 0, &$3, &$5, 2);
354 | INSTR_NOP
356 TRACE("NOP\n");
357 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NOP, 0, 0, 0, 0, 0, 0);
359 | INSTR_MOV omods dreg ',' sregs
361 TRACE("MOV\n");
362 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOV, $2.mod, $2.shift, 0, &$3, &$5, 1);
364 | INSTR_SUB omods dreg ',' sregs
366 TRACE("SUB\n");
367 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SUB, $2.mod, $2.shift, 0, &$3, &$5, 2);
369 | INSTR_MAD omods dreg ',' sregs
371 TRACE("MAD\n");
372 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAD, $2.mod, $2.shift, 0, &$3, &$5, 3);
374 | INSTR_MUL omods dreg ',' sregs
376 TRACE("MUL\n");
377 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MUL, $2.mod, $2.shift, 0, &$3, &$5, 2);
379 | INSTR_RCP omods dreg ',' sregs
381 TRACE("RCP\n");
382 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RCP, $2.mod, $2.shift, 0, &$3, &$5, 1);
384 | INSTR_RSQ omods dreg ',' sregs
386 TRACE("RSQ\n");
387 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RSQ, $2.mod, $2.shift, 0, &$3, &$5, 1);
389 | INSTR_DP3 omods dreg ',' sregs
391 TRACE("DP3\n");
392 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP3, $2.mod, $2.shift, 0, &$3, &$5, 2);
394 | INSTR_DP4 omods dreg ',' sregs
396 TRACE("DP4\n");
397 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP4, $2.mod, $2.shift, 0, &$3, &$5, 2);
399 | INSTR_MIN omods dreg ',' sregs
401 TRACE("MIN\n");
402 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MIN, $2.mod, $2.shift, 0, &$3, &$5, 2);
404 | INSTR_MAX omods dreg ',' sregs
406 TRACE("MAX\n");
407 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAX, $2.mod, $2.shift, 0, &$3, &$5, 2);
409 | INSTR_SLT omods dreg ',' sregs
411 TRACE("SLT\n");
412 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SLT, $2.mod, $2.shift, 0, &$3, &$5, 2);
414 | INSTR_SGE omods dreg ',' sregs
416 TRACE("SGE\n");
417 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGE, $2.mod, $2.shift, 0, &$3, &$5, 2);
419 | INSTR_ABS omods dreg ',' sregs
421 TRACE("ABS\n");
422 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ABS, $2.mod, $2.shift, 0, &$3, &$5, 1);
424 | INSTR_EXP omods dreg ',' sregs
426 TRACE("EXP\n");
427 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXP, $2.mod, $2.shift, 0, &$3, &$5, 1);
429 | INSTR_LOG omods dreg ',' sregs
431 TRACE("LOG\n");
432 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOG, $2.mod, $2.shift, 0, &$3, &$5, 1);
434 | INSTR_LOGP omods dreg ',' sregs
436 TRACE("LOGP\n");
437 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOGP, $2.mod, $2.shift, 0, &$3, &$5, 1);
439 | INSTR_EXPP omods dreg ',' sregs
441 TRACE("EXPP\n");
442 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXPP, $2.mod, $2.shift, 0, &$3, &$5, 1);
444 | INSTR_DST omods dreg ',' sregs
446 TRACE("DST\n");
447 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DST, $2.mod, $2.shift, 0, &$3, &$5, 2);
449 | INSTR_LRP omods dreg ',' sregs
451 TRACE("LRP\n");
452 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LRP, $2.mod, $2.shift, 0, &$3, &$5, 3);
454 | INSTR_FRC omods dreg ',' sregs
456 TRACE("FRC\n");
457 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_FRC, $2.mod, $2.shift, 0, &$3, &$5, 1);
459 | INSTR_POW omods dreg ',' sregs
461 TRACE("POW\n");
462 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_POW, $2.mod, $2.shift, 0, &$3, &$5, 2);
464 | INSTR_CRS omods dreg ',' sregs
466 TRACE("CRS\n");
467 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CRS, $2.mod, $2.shift, 0, &$3, &$5, 2);
469 | INSTR_SGN omods dreg ',' sregs
471 TRACE("SGN\n");
472 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGN, $2.mod, $2.shift, 0, &$3, &$5, 3);
474 | INSTR_NRM omods dreg ',' sregs
476 TRACE("NRM\n");
477 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NRM, $2.mod, $2.shift, 0, &$3, &$5, 1);
479 | INSTR_SINCOS omods dreg ',' sregs
481 TRACE("SINCOS\n");
482 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SINCOS, $2.mod, $2.shift, 0, &$3, &$5, 1);
484 | INSTR_M4x4 omods dreg ',' sregs
486 TRACE("M4x4\n");
487 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
489 | INSTR_M4x3 omods dreg ',' sregs
491 TRACE("M4x3\n");
492 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
494 | INSTR_M3x4 omods dreg ',' sregs
496 TRACE("M3x4\n");
497 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
499 | INSTR_M3x3 omods dreg ',' sregs
501 TRACE("M3x3\n");
502 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
504 | INSTR_M3x2 omods dreg ',' sregs
506 TRACE("M3x2\n");
507 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x2, $2.mod, $2.shift, 0, &$3, &$5, 2);
509 | INSTR_DCL dclusage REG_OUTPUT
511 struct shader_reg reg;
512 TRACE("Output reg declaration\n");
513 ZeroMemory(&reg, sizeof(reg));
514 reg.type = BWRITERSPR_OUTPUT;
515 reg.regnum = $3;
516 reg.rel_reg = NULL;
517 reg.srcmod = 0;
518 reg.writemask = BWRITERSP_WRITEMASK_ALL;
519 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
521 | INSTR_DCL dclusage REG_OUTPUT writemask
523 struct shader_reg reg;
524 TRACE("Output reg declaration\n");
525 ZeroMemory(&reg, sizeof(reg));
526 reg.type = BWRITERSPR_OUTPUT;
527 reg.regnum = $3;
528 reg.rel_reg = NULL;
529 reg.srcmod = 0;
530 reg.writemask = $4;
531 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
533 | INSTR_DCL dclusage REG_INPUT
535 struct shader_reg reg;
536 TRACE("Input reg declaration\n");
537 ZeroMemory(&reg, sizeof(reg));
538 reg.type = BWRITERSPR_INPUT;
539 reg.regnum = $3;
540 reg.rel_reg = NULL;
541 reg.srcmod = 0;
542 reg.writemask = BWRITERSP_WRITEMASK_ALL;
543 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, &reg);
545 | INSTR_DCL dclusage REG_INPUT writemask
547 struct shader_reg reg;
548 TRACE("Input reg declaration\n");
549 ZeroMemory(&reg, sizeof(reg));
550 reg.type = BWRITERSPR_INPUT;
551 reg.regnum = $3;
552 reg.rel_reg = NULL;
553 reg.srcmod = 0;
554 reg.writemask = $4;
555 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, &reg);
557 | INSTR_DCL sampdcl REG_SAMPLER
559 TRACE("Sampler declared\n");
560 asm_ctx.funcs->dcl_sampler(&asm_ctx, $2, $3, asm_ctx.line_no);
562 | INSTR_DCL sampdcl REG_INPUT
564 TRACE("Error rule: sampler decl of input reg\n");
565 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of input regs is not valid\n",
566 asm_ctx.line_no);
567 set_parse_status(&asm_ctx, PARSE_WARN);
569 | INSTR_DCL sampdcl REG_OUTPUT
571 TRACE("Error rule: sampler decl of output reg\n");
572 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of output regs is not valid\n",
573 asm_ctx.line_no);
574 set_parse_status(&asm_ctx, PARSE_WARN);
576 | INSTR_REP sregs
578 TRACE("REP\n");
579 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_REP, 0, 0, 0, 0, &$2, 1);
581 | INSTR_ENDREP
583 TRACE("ENDREP\n");
584 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDREP, 0, 0, 0, 0, 0, 0);
586 | INSTR_IF sregs
588 TRACE("IF\n");
589 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IF, 0, 0, 0, 0, &$2, 1);
591 | INSTR_IF comp sregs
593 TRACE("IFC\n");
594 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IFC, 0, 0, $2, 0, &$3, 2);
596 | INSTR_ELSE
598 TRACE("ELSE\n");
599 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ELSE, 0, 0, 0, 0, 0, 0);
601 | INSTR_ENDIF
603 TRACE("ENDIF\n");
604 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDIF, 0, 0, 0, 0, 0, 0);
606 | INSTR_BREAK
608 TRACE("BREAK\n");
609 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAK, 0, 0, 0, 0, 0, 0);
611 | INSTR_BREAK comp sregs
613 TRACE("BREAKC\n");
614 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKC, 0, 0, $2, 0, &$3, 2);
616 | INSTR_BREAKP sregs
618 TRACE("BREAKP\n");
619 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKP, 0, 0, 0, 0, &$2, 1);
621 | INSTR_CALL sregs
623 TRACE("CALL\n");
624 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALL, 0, 0, 0, 0, &$2, 1);
626 | INSTR_CALLNZ sregs
628 TRACE("CALLNZ\n");
629 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALLNZ, 0, 0, 0, 0, &$2, 2);
631 | INSTR_LOOP sregs
633 TRACE("LOOP\n");
634 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOOP, 0, 0, 0, 0, &$2, 2);
636 | INSTR_RET
638 TRACE("RET\n");
639 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RET, 0, 0, 0, 0, 0, 0);
641 | INSTR_ENDLOOP
643 TRACE("ENDLOOP\n");
644 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDLOOP, 0, 0, 0, 0, 0, 0);
646 | INSTR_LABEL sregs
648 TRACE("LABEL\n");
649 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LABEL, 0, 0, 0, 0, &$2, 1);
651 | INSTR_SETP comp dreg ',' sregs
653 TRACE("SETP\n");
654 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SETP, 0, 0, $2, &$3, &$5, 2);
656 | INSTR_TEXLDL omods dreg ',' sregs
658 TRACE("TEXLDL\n");
659 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDL, $2.mod, $2.shift, 0, &$3, &$5, 2);
661 | INSTR_LIT omods dreg ',' sregs
663 TRACE("LIT\n");
664 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LIT, $2.mod, $2.shift, 0, &$3, &$5, 1);
666 | INSTR_MOVA omods dreg ',' sregs
668 TRACE("MOVA\n");
669 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOVA, $2.mod, $2.shift, 0, &$3, &$5, 1);
672 dreg: dreg_name rel_reg
674 $$.regnum = $1.regnum;
675 $$.type = $1.type;
676 $$.writemask = BWRITERSP_WRITEMASK_ALL;
677 $$.srcmod = BWRITERSPSM_NONE;
678 set_rel_reg(&$$, &$2);
680 | dreg_name writemask
682 $$.regnum = $1.regnum;
683 $$.type = $1.type;
684 $$.writemask = $2;
685 $$.srcmod = BWRITERSPSM_NONE;
686 $$.rel_reg = NULL;
689 dreg_name: REG_TEMP
691 $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
693 | REG_OUTPUT
695 $$.regnum = $1; $$.type = BWRITERSPR_OUTPUT;
697 | REG_INPUT
699 asmparser_message(&asm_ctx, "Line %u: Register v%u is not a valid destination register\n",
700 asm_ctx.line_no, $1);
701 set_parse_status(&asm_ctx, PARSE_WARN);
703 | REG_CONSTFLOAT
705 asmparser_message(&asm_ctx, "Line %u: Register c%u is not a valid destination register\n",
706 asm_ctx.line_no, $1);
707 set_parse_status(&asm_ctx, PARSE_WARN);
709 | REG_CONSTINT
711 asmparser_message(&asm_ctx, "Line %u: Register i%u is not a valid destination register\n",
712 asm_ctx.line_no, $1);
713 set_parse_status(&asm_ctx, PARSE_WARN);
715 | REG_CONSTBOOL
717 asmparser_message(&asm_ctx, "Line %u: Register b%u is not a valid destination register\n",
718 asm_ctx.line_no, $1);
719 set_parse_status(&asm_ctx, PARSE_WARN);
721 | REG_TEXTURE
723 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
725 | REG_TEXCRDOUT
727 $$.regnum = $1; $$.type = BWRITERSPR_TEXCRDOUT;
729 | REG_SAMPLER
731 asmparser_message(&asm_ctx, "Line %u: Register s%u is not a valid destination register\n",
732 asm_ctx.line_no, $1);
733 set_parse_status(&asm_ctx, PARSE_WARN);
735 | REG_OPOS
737 $$.regnum = BWRITERSRO_POSITION; $$.type = BWRITERSPR_RASTOUT;
739 | REG_OPTS
741 $$.regnum = BWRITERSRO_POINT_SIZE; $$.type = BWRITERSPR_RASTOUT;
743 | REG_OFOG
745 $$.regnum = BWRITERSRO_FOG; $$.type = BWRITERSPR_RASTOUT;
747 | REG_VERTEXCOLOR
749 $$.regnum = $1; $$.type = BWRITERSPR_ATTROUT;
751 | REG_FRAGCOLOR
753 $$.regnum = $1; $$.type = BWRITERSPR_COLOROUT;
755 | REG_FRAGDEPTH
757 $$.regnum = 0; $$.type = BWRITERSPR_DEPTHOUT;
759 | REG_PREDICATE
761 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
763 | REG_VPOS
765 asmparser_message(&asm_ctx, "Line %u: Register vPos is not a valid destination register\n",
766 asm_ctx.line_no);
767 set_parse_status(&asm_ctx, PARSE_WARN);
769 | REG_VFACE
771 asmparser_message(&asm_ctx, "Line %u: Register vFace is not a valid destination register\n",
772 asm_ctx.line_no);
773 set_parse_status(&asm_ctx, PARSE_WARN);
775 | REG_ADDRESS
777 /* index 0 is hardcoded for the addr register */
778 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
780 | REG_LOOP
782 asmparser_message(&asm_ctx, "Line %u: Register aL is not a valid destination register\n",
783 asm_ctx.line_no);
784 set_parse_status(&asm_ctx, PARSE_WARN);
787 writemask: '.' wm_components
789 if($2.writemask == SWIZZLE_ERR) {
790 asmparser_message(&asm_ctx, "Line %u: Invalid writemask specified\n",
791 asm_ctx.line_no);
792 set_parse_status(&asm_ctx, PARSE_ERR);
793 /* Provide a correct writemask to prevent following complaints */
794 $$ = BWRITERSP_WRITEMASK_ALL;
796 else {
797 $$ = $2.writemask;
798 TRACE("Writemask: %x\n", $$);
802 wm_components: COMPONENT
804 $$.writemask = 1 << $1;
805 $$.last = $1;
806 $$.idx = 1;
808 | wm_components COMPONENT
810 if($1.writemask == SWIZZLE_ERR || $1.idx == 4)
811 /* Wrong writemask */
812 $$.writemask = SWIZZLE_ERR;
813 else {
814 if($2 <= $1.last)
815 $$.writemask = SWIZZLE_ERR;
816 else {
817 $$.writemask = $1.writemask | (1 << $2);
818 $$.idx = $1.idx + 1;
823 swizzle: /* empty */
825 $$ = BWRITERVS_NOSWIZZLE;
826 TRACE("Default swizzle: %08x\n", $$);
828 | '.' sw_components
830 if($2.swizzle == SWIZZLE_ERR) {
831 asmparser_message(&asm_ctx, "Line %u: Invalid swizzle\n",
832 asm_ctx.line_no);
833 set_parse_status(&asm_ctx, PARSE_ERR);
834 /* Provide a correct swizzle to prevent following complaints */
835 $$ = BWRITERVS_NOSWIZZLE;
837 else {
838 DWORD last, i;
840 $$ = $2.swizzle << BWRITERVS_SWIZZLE_SHIFT;
841 /* Fill the swizzle by extending the last component */
842 last = ($2.swizzle >> 2 * ($2.idx - 1)) & 0x03;
843 for(i = $2.idx; i < 4; i++){
844 $$ |= last << (BWRITERVS_SWIZZLE_SHIFT + 2 * i);
846 TRACE("Got a swizzle: %08x\n", $$);
850 sw_components: COMPONENT
852 $$.swizzle = $1;
853 $$.idx = 1;
855 | sw_components COMPONENT
857 if($1.idx == 4) {
858 /* Too many sw_components */
859 $$.swizzle = SWIZZLE_ERR;
860 $$.idx = 4;
862 else {
863 $$.swizzle = $1.swizzle | ($2 << 2 * $1.idx);
864 $$.idx = $1.idx + 1;
868 omods: /* Empty */
870 $$.mod = 0;
871 $$.shift = 0;
873 | omods omodifier
875 $$.mod = $1.mod | $2.mod;
876 if($1.shift && $2.shift) {
877 asmparser_message(&asm_ctx, "Line %u: More than one shift flag\n",
878 asm_ctx.line_no);
879 set_parse_status(&asm_ctx, PARSE_ERR);
880 $$.shift = $1.shift;
881 } else {
882 $$.shift = $1.shift | $2.shift;
886 omodifier: MOD_SAT
888 $$.mod = BWRITERSPDM_SATURATE;
889 $$.shift = 0;
891 | MOD_PP
893 $$.mod = BWRITERSPDM_PARTIALPRECISION;
894 $$.shift = 0;
896 | MOD_CENTROID
898 $$.mod = BWRITERSPDM_MSAMPCENTROID;
899 $$.shift = 0;
902 sregs: sreg
904 $$.reg[0] = $1;
905 $$.count = 1;
907 | sregs ',' sreg
909 if($$.count == MAX_SRC_REGS){
910 asmparser_message(&asm_ctx, "Line %u: Too many source registers in this instruction\n",
911 asm_ctx.line_no);
912 set_parse_status(&asm_ctx, PARSE_ERR);
914 else
915 $$.reg[$$.count++] = $3;
918 sreg: sreg_name rel_reg swizzle
920 $$.type = $1.type;
921 $$.regnum = $1.regnum;
922 $$.swizzle = $3;
923 $$.srcmod = BWRITERSPSM_NONE;
924 set_rel_reg(&$$, &$2);
926 | sreg_name rel_reg smod swizzle
928 $$.type = $1.type;
929 $$.regnum = $1.regnum;
930 set_rel_reg(&$$, &$2);
931 $$.srcmod = $3;
932 $$.swizzle = $4;
934 | '-' sreg_name rel_reg swizzle
936 $$.type = $2.type;
937 $$.regnum = $2.regnum;
938 $$.srcmod = BWRITERSPSM_NEG;
939 set_rel_reg(&$$, &$3);
940 $$.swizzle = $4;
942 | '-' sreg_name rel_reg smod swizzle
944 $$.type = $2.type;
945 $$.regnum = $2.regnum;
946 set_rel_reg(&$$, &$3);
947 switch($4) {
948 case BWRITERSPSM_ABS: $$.srcmod = BWRITERSPSM_ABSNEG; break;
949 default:
950 FIXME("Unhandled combination of NEGATE and %u\n", $4);
952 $$.swizzle = $5;
954 | SMOD_NOT sreg_name swizzle
956 $$.type = $2.type;
957 $$.regnum = $2.regnum;
958 $$.rel_reg = NULL;
959 $$.srcmod = BWRITERSPSM_NOT;
960 $$.swizzle = $3;
963 rel_reg: /* empty */
965 $$.has_rel_reg = FALSE;
966 $$.additional_offset = 0;
968 | '[' immsum ']'
970 $$.has_rel_reg = FALSE;
971 $$.additional_offset = $2.val;
973 | '[' relreg_name swizzle ']'
975 $$.has_rel_reg = TRUE;
976 $$.type = $2.type;
977 $$.additional_offset = 0;
978 $$.rel_regnum = $2.regnum;
979 $$.swizzle = $3;
981 | '[' immsum '+' relreg_name swizzle ']'
983 $$.has_rel_reg = TRUE;
984 $$.type = $4.type;
985 $$.additional_offset = $2.val;
986 $$.rel_regnum = $4.regnum;
987 $$.swizzle = $5;
989 | '[' relreg_name swizzle '+' immsum ']'
991 $$.has_rel_reg = TRUE;
992 $$.type = $2.type;
993 $$.additional_offset = $5.val;
994 $$.rel_regnum = $2.regnum;
995 $$.swizzle = $3;
997 | '[' immsum '+' relreg_name swizzle '+' immsum ']'
999 $$.has_rel_reg = TRUE;
1000 $$.type = $4.type;
1001 $$.additional_offset = $2.val + $7.val;
1002 $$.rel_regnum = $4.regnum;
1003 $$.swizzle = $5;
1006 immsum: IMMVAL
1008 if(!$1.integer) {
1009 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1010 asm_ctx.line_no, $1.val);
1011 set_parse_status(&asm_ctx, PARSE_ERR);
1013 $$.val = $1.val;
1015 | immsum '+' IMMVAL
1017 if(!$3.integer) {
1018 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1019 asm_ctx.line_no, $3.val);
1020 set_parse_status(&asm_ctx, PARSE_ERR);
1022 $$.val = $1.val + $3.val;
1025 smod: SMOD_ABS
1027 $$ = BWRITERSPSM_ABS;
1030 relreg_name: REG_ADDRESS
1032 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1034 | REG_LOOP
1036 $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1039 sreg_name: REG_TEMP
1041 $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
1043 | REG_OUTPUT
1045 asmparser_message(&asm_ctx, "Line %u: Register o%u is not a valid source register\n",
1046 asm_ctx.line_no, $1);
1047 set_parse_status(&asm_ctx, PARSE_WARN);
1049 | REG_INPUT
1051 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1053 | REG_CONSTFLOAT
1055 $$.regnum = $1; $$.type = BWRITERSPR_CONST;
1057 | REG_CONSTINT
1059 $$.regnum = $1; $$.type = BWRITERSPR_CONSTINT;
1061 | REG_CONSTBOOL
1063 $$.regnum = $1; $$.type = BWRITERSPR_CONSTBOOL;
1065 | REG_TEXTURE
1067 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1069 | REG_TEXCRDOUT
1071 asmparser_message(&asm_ctx, "Line %u: Register oT%u is not a valid source register\n",
1072 asm_ctx.line_no, $1);
1073 set_parse_status(&asm_ctx, PARSE_WARN);
1075 | REG_SAMPLER
1077 $$.regnum = $1; $$.type = BWRITERSPR_SAMPLER;
1079 | REG_OPOS
1081 asmparser_message(&asm_ctx, "Line %u: Register oPos is not a valid source register\n",
1082 asm_ctx.line_no);
1083 set_parse_status(&asm_ctx, PARSE_WARN);
1085 | REG_OFOG
1087 asmparser_message(&asm_ctx, "Line %u: Register oFog is not a valid source register\n",
1088 asm_ctx.line_no);
1089 set_parse_status(&asm_ctx, PARSE_WARN);
1091 | REG_VERTEXCOLOR
1093 asmparser_message(&asm_ctx, "Line %u: Register oD%u is not a valid source register\n",
1094 asm_ctx.line_no, $1);
1095 set_parse_status(&asm_ctx, PARSE_WARN);
1097 | REG_FRAGCOLOR
1099 asmparser_message(&asm_ctx, "Line %u: Register oC%u is not a valid source register\n",
1100 asm_ctx.line_no, $1);
1101 set_parse_status(&asm_ctx, PARSE_WARN);
1103 | REG_FRAGDEPTH
1105 asmparser_message(&asm_ctx, "Line %u: Register oDepth is not a valid source register\n",
1106 asm_ctx.line_no);
1107 set_parse_status(&asm_ctx, PARSE_WARN);
1109 | REG_PREDICATE
1111 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
1113 | REG_VPOS
1115 $$.regnum = 0; $$.type = BWRITERSPR_MISCTYPE;
1117 | REG_VFACE
1119 $$.regnum = 1; $$.type = BWRITERSPR_MISCTYPE;
1121 | REG_ADDRESS
1123 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1125 | REG_LOOP
1127 $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1129 | REG_LABEL
1131 $$.regnum = $1; $$.type = BWRITERSPR_LABEL;
1134 comp: COMP_GT { $$ = BWRITER_COMPARISON_GT; }
1135 | COMP_LT { $$ = BWRITER_COMPARISON_LT; }
1136 | COMP_GE { $$ = BWRITER_COMPARISON_GE; }
1137 | COMP_LE { $$ = BWRITER_COMPARISON_LE; }
1138 | COMP_EQ { $$ = BWRITER_COMPARISON_EQ; }
1139 | COMP_NE { $$ = BWRITER_COMPARISON_NE; }
1141 dclusage: USAGE_POSITION
1143 TRACE("dcl_position%u\n", $1);
1144 $$.regnum = $1;
1145 $$.dclusage = BWRITERDECLUSAGE_POSITION;
1147 | USAGE_BLENDWEIGHT
1149 TRACE("dcl_blendweight%u\n", $1);
1150 $$.regnum = $1;
1151 $$.dclusage = BWRITERDECLUSAGE_BLENDWEIGHT;
1153 | USAGE_BLENDINDICES
1155 TRACE("dcl_blendindices%u\n", $1);
1156 $$.regnum = $1;
1157 $$.dclusage = BWRITERDECLUSAGE_BLENDINDICES;
1159 | USAGE_NORMAL
1161 TRACE("dcl_normal%u\n", $1);
1162 $$.regnum = $1;
1163 $$.dclusage = BWRITERDECLUSAGE_NORMAL;
1165 | USAGE_PSIZE
1167 TRACE("dcl_psize%u\n", $1);
1168 $$.regnum = $1;
1169 $$.dclusage = BWRITERDECLUSAGE_PSIZE;
1171 | USAGE_TEXCOORD
1173 TRACE("dcl_texcoord%u\n", $1);
1174 $$.regnum = $1;
1175 $$.dclusage = BWRITERDECLUSAGE_TEXCOORD;
1177 | USAGE_TANGENT
1179 TRACE("dcl_tangent%u\n", $1);
1180 $$.regnum = $1;
1181 $$.dclusage = BWRITERDECLUSAGE_TANGENT;
1183 | USAGE_BINORMAL
1185 TRACE("dcl_binormal%u\n", $1);
1186 $$.regnum = $1;
1187 $$.dclusage = BWRITERDECLUSAGE_BINORMAL;
1189 | USAGE_TESSFACTOR
1191 TRACE("dcl_tessfactor%u\n", $1);
1192 $$.regnum = $1;
1193 $$.dclusage = BWRITERDECLUSAGE_TESSFACTOR;
1195 | USAGE_POSITIONT
1197 TRACE("dcl_positiont%u\n", $1);
1198 $$.regnum = $1;
1199 $$.dclusage = BWRITERDECLUSAGE_POSITIONT;
1201 | USAGE_COLOR
1203 TRACE("dcl_color%u\n", $1);
1204 $$.regnum = $1;
1205 $$.dclusage = BWRITERDECLUSAGE_COLOR;
1207 | USAGE_FOG
1209 TRACE("dcl_fog%u\n", $1);
1210 $$.regnum = $1;
1211 $$.dclusage = BWRITERDECLUSAGE_FOG;
1213 | USAGE_DEPTH
1215 TRACE("dcl_depth%u\n", $1);
1216 $$.regnum = $1;
1217 $$.dclusage = BWRITERDECLUSAGE_DEPTH;
1219 | USAGE_SAMPLE
1221 TRACE("dcl_sample%u\n", $1);
1222 $$.regnum = $1;
1223 $$.dclusage = BWRITERDECLUSAGE_SAMPLE;
1226 sampdcl: SAMPTYPE_1D
1228 $$ = BWRITERSTT_1D;
1230 | SAMPTYPE_2D
1232 $$ = BWRITERSTT_2D;
1234 | SAMPTYPE_CUBE
1236 $$ = BWRITERSTT_CUBE;
1238 | SAMPTYPE_VOLUME
1240 $$ = BWRITERSTT_VOLUME;
1243 predicate: '(' REG_PREDICATE swizzle ')'
1245 $$.type = BWRITERSPR_PREDICATE;
1246 $$.regnum = 0;
1247 $$.rel_reg = NULL;
1248 $$.srcmod = BWRITERSPSM_NONE;
1249 $$.swizzle = $3;
1251 | '(' SMOD_NOT REG_PREDICATE swizzle ')'
1253 $$.type = BWRITERSPR_PREDICATE;
1254 $$.regnum = 0;
1255 $$.rel_reg = NULL;
1256 $$.srcmod = BWRITERSPSM_NOT;
1257 $$.swizzle = $4;
1262 void asmshader_error (char const *s) {
1263 asmparser_message(&asm_ctx, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no, s);
1264 set_parse_status(&asm_ctx, PARSE_ERR);
1267 /* Error reporting function */
1268 void asmparser_message(struct asm_parser *ctx, const char *fmt, ...) {
1269 va_list args;
1270 char* newbuffer;
1271 int rc, newsize;
1273 if(ctx->messagecapacity == 0) {
1274 ctx->messages = asm_alloc(MESSAGEBUFFER_INITIAL_SIZE);
1275 if(ctx->messages == NULL) {
1276 ERR("Error allocating memory for parser messages\n");
1277 return;
1279 ctx->messagecapacity = MESSAGEBUFFER_INITIAL_SIZE;
1282 while(1) {
1283 va_start(args, fmt);
1284 rc = vsnprintf(ctx->messages + ctx->messagesize,
1285 ctx->messagecapacity - ctx->messagesize, fmt, args);
1286 va_end(args);
1288 if (rc < 0 || /* C89 */
1289 rc >= ctx->messagecapacity - ctx->messagesize) { /* C99 */
1290 /* Resize the buffer */
1291 newsize = ctx->messagecapacity * 2;
1292 newbuffer = asm_realloc(ctx->messages, newsize);
1293 if(newbuffer == NULL){
1294 ERR("Error reallocating memory for parser messages\n");
1295 return;
1297 ctx->messages = newbuffer;
1298 ctx->messagecapacity = newsize;
1299 } else {
1300 ctx->messagesize += rc;
1301 return;
1306 /* New status is the worst between current status and parameter value */
1307 void set_parse_status(struct asm_parser *ctx, enum parse_status status) {
1308 if(status == PARSE_ERR) ctx->status = PARSE_ERR;
1309 else if(status == PARSE_WARN && ctx->status == PARSE_SUCCESS) ctx->status = PARSE_WARN;
1312 struct bwriter_shader *parse_asm_shader(char **messages) {
1313 struct bwriter_shader *ret = NULL;
1315 asm_ctx.shader = NULL;
1316 asm_ctx.status = PARSE_SUCCESS;
1317 asm_ctx.messagesize = asm_ctx.messagecapacity = 0;
1318 asm_ctx.line_no = 1;
1320 asmshader_parse();
1322 if(asm_ctx.status != PARSE_ERR) ret = asm_ctx.shader;
1323 else if(asm_ctx.shader) SlDeleteShader(asm_ctx.shader);
1325 if(messages) {
1326 if(asm_ctx.messagesize) {
1327 /* Shrink the buffer to the used size */
1328 *messages = asm_realloc(asm_ctx.messages, asm_ctx.messagesize + 1);
1329 if(!*messages) {
1330 ERR("Out of memory, no messages reported\n");
1331 asm_free(asm_ctx.messages);
1333 } else {
1334 *messages = NULL;
1336 } else {
1337 if(asm_ctx.messagecapacity) asm_free(asm_ctx.messages);
1340 return ret;