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