ddraw: Use unsafe_impl_from_IDirect3DViewport for application provided interfaces.
[wine/multimedia.git] / dlls / d3dcompiler_43 / asmshader.y
blob4360d9f5060f8c5ba1b7f695741c075126687088
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 "d3dcompiler_private.h"
29 #include <stdio.h>
31 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
33 struct asm_parser asm_ctx;
35 /* Error reporting function */
36 void asmparser_message(struct asm_parser *ctx, const char *fmt, ...) {
37 va_list args;
38 char* newbuffer;
39 int rc, newsize;
41 if(ctx->messagecapacity == 0) {
42 ctx->messages = asm_alloc(MESSAGEBUFFER_INITIAL_SIZE);
43 if(ctx->messages == NULL) {
44 ERR("Error allocating memory for parser messages\n");
45 return;
47 ctx->messagecapacity = MESSAGEBUFFER_INITIAL_SIZE;
50 while(1) {
51 va_start(args, fmt);
52 rc = vsnprintf(ctx->messages + ctx->messagesize,
53 ctx->messagecapacity - ctx->messagesize, fmt, args);
54 va_end(args);
56 if (rc < 0 || /* C89 */
57 rc >= ctx->messagecapacity - ctx->messagesize) { /* C99 */
58 /* Resize the buffer */
59 newsize = ctx->messagecapacity * 2;
60 newbuffer = asm_realloc(ctx->messages, newsize);
61 if(newbuffer == NULL){
62 ERR("Error reallocating memory for parser messages\n");
63 return;
65 ctx->messages = newbuffer;
66 ctx->messagecapacity = newsize;
67 } else {
68 ctx->messagesize += rc;
69 return;
74 static void asmshader_error(char const *s) {
75 asmparser_message(&asm_ctx, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no, s);
76 set_parse_status(&asm_ctx, PARSE_ERR);
79 static void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
80 /* We can have an additional offset without true relative addressing
81 * ex. c2[ 4 ] */
82 reg->regnum += rel->additional_offset;
83 if(!rel->has_rel_reg) {
84 reg->rel_reg = NULL;
85 } else {
86 reg->rel_reg = asm_alloc(sizeof(*reg->rel_reg));
87 if(!reg->rel_reg) {
88 return;
90 reg->rel_reg->type = rel->type;
91 reg->rel_reg->u.swizzle = rel->swizzle;
92 reg->rel_reg->regnum = rel->rel_regnum;
96 /* Needed lexer functions declarations */
97 int asmshader_lex(void);
102 %union {
103 struct {
104 float val;
105 BOOL integer;
106 } immval;
107 BOOL immbool;
108 unsigned int regnum;
109 struct shader_reg reg;
110 DWORD srcmod;
111 DWORD writemask;
112 struct {
113 DWORD writemask;
114 DWORD idx;
115 DWORD last;
116 } wm_components;
117 DWORD swizzle;
118 struct {
119 DWORD swizzle;
120 DWORD idx;
121 } sw_components;
122 DWORD component;
123 struct {
124 DWORD mod;
125 DWORD shift;
126 } modshift;
127 BWRITER_COMPARISON_TYPE comptype;
128 struct {
129 DWORD dclusage;
130 unsigned int regnum;
131 } declaration;
132 BWRITERSAMPLER_TEXTURE_TYPE samplertype;
133 struct rel_reg rel_reg;
134 struct src_regs sregs;
137 /* Common instructions between vertex and pixel shaders */
138 %token INSTR_ADD
139 %token INSTR_NOP
140 %token INSTR_MOV
141 %token INSTR_SUB
142 %token INSTR_MAD
143 %token INSTR_MUL
144 %token INSTR_RCP
145 %token INSTR_RSQ
146 %token INSTR_DP3
147 %token INSTR_DP4
148 %token INSTR_MIN
149 %token INSTR_MAX
150 %token INSTR_SLT
151 %token INSTR_SGE
152 %token INSTR_ABS
153 %token INSTR_EXP
154 %token INSTR_LOG
155 %token INSTR_EXPP
156 %token INSTR_LOGP
157 %token INSTR_DST
158 %token INSTR_LRP
159 %token INSTR_FRC
160 %token INSTR_POW
161 %token INSTR_CRS
162 %token INSTR_SGN
163 %token INSTR_NRM
164 %token INSTR_SINCOS
165 %token INSTR_M4x4
166 %token INSTR_M4x3
167 %token INSTR_M3x4
168 %token INSTR_M3x3
169 %token INSTR_M3x2
170 %token INSTR_DCL
171 %token INSTR_DEF
172 %token INSTR_DEFB
173 %token INSTR_DEFI
174 %token INSTR_REP
175 %token INSTR_ENDREP
176 %token INSTR_IF
177 %token INSTR_ELSE
178 %token INSTR_ENDIF
179 %token INSTR_BREAK
180 %token INSTR_BREAKP
181 %token INSTR_CALL
182 %token INSTR_CALLNZ
183 %token INSTR_LOOP
184 %token INSTR_RET
185 %token INSTR_ENDLOOP
186 %token INSTR_LABEL
187 %token INSTR_SETP
188 %token INSTR_TEXLDL
190 /* Vertex shader only instructions */
191 %token INSTR_LIT
192 %token INSTR_MOVA
194 /* Pixel shader only instructions */
195 %token INSTR_CND
196 %token INSTR_CMP
197 %token INSTR_DP2ADD
198 %token INSTR_TEXCOORD
199 %token INSTR_TEXCRD
200 %token INSTR_TEXKILL
201 %token INSTR_TEX
202 %token INSTR_TEXLD
203 %token INSTR_TEXBEM
204 %token INSTR_TEXBEML
205 %token INSTR_TEXREG2AR
206 %token INSTR_TEXREG2GB
207 %token INSTR_TEXREG2RGB
208 %token INSTR_TEXM3x2PAD
209 %token INSTR_TEXM3x2TEX
210 %token INSTR_TEXM3x3PAD
211 %token INSTR_TEXM3x3SPEC
212 %token INSTR_TEXM3x3VSPEC
213 %token INSTR_TEXM3x3TEX
214 %token INSTR_TEXDP3TEX
215 %token INSTR_TEXM3x2DEPTH
216 %token INSTR_TEXDP3
217 %token INSTR_TEXM3x3
218 %token INSTR_TEXDEPTH
219 %token INSTR_BEM
220 %token INSTR_DSX
221 %token INSTR_DSY
222 %token INSTR_TEXLDP
223 %token INSTR_TEXLDB
224 %token INSTR_TEXLDD
225 %token INSTR_PHASE
227 /* Registers */
228 %token <regnum> REG_TEMP
229 %token <regnum> REG_OUTPUT
230 %token <regnum> REG_INPUT
231 %token <regnum> REG_CONSTFLOAT
232 %token <regnum> REG_CONSTINT
233 %token <regnum> REG_CONSTBOOL
234 %token <regnum> REG_TEXTURE
235 %token <regnum> REG_SAMPLER
236 %token <regnum> REG_TEXCRDOUT
237 %token REG_OPOS
238 %token REG_OFOG
239 %token REG_OPTS
240 %token <regnum> REG_VERTEXCOLOR
241 %token <regnum> REG_FRAGCOLOR
242 %token REG_FRAGDEPTH
243 %token REG_VPOS
244 %token REG_VFACE
245 %token REG_ADDRESS
246 %token REG_LOOP
247 %token REG_PREDICATE
248 %token <regnum> REG_LABEL
250 /* Version tokens */
251 %token VER_VS10
252 %token VER_VS11
253 %token VER_VS20
254 %token VER_VS2X
255 %token VER_VS30
257 %token VER_PS10
258 %token VER_PS11
259 %token VER_PS12
260 %token VER_PS13
261 %token VER_PS14
262 %token VER_PS20
263 %token VER_PS2X
264 %token VER_PS30
266 /* Output modifiers */
267 %token SHIFT_X2
268 %token SHIFT_X4
269 %token SHIFT_X8
270 %token SHIFT_D2
271 %token SHIFT_D4
272 %token SHIFT_D8
273 %token MOD_SAT
274 %token MOD_PP
275 %token MOD_CENTROID
277 /* Compare tokens */
278 %token COMP_GT
279 %token COMP_LT
280 %token COMP_GE
281 %token COMP_LE
282 %token COMP_EQ
283 %token COMP_NE
285 /* Source register modifiers */
286 %token SMOD_BIAS
287 %token SMOD_SCALEBIAS
288 %token SMOD_DZ
289 %token SMOD_DW
290 %token SMOD_ABS
291 %token SMOD_NOT
293 /* Sampler types */
294 %token SAMPTYPE_1D
295 %token SAMPTYPE_2D
296 %token SAMPTYPE_CUBE
297 %token SAMPTYPE_VOLUME
299 /* Usage declaration tokens */
300 %token <regnum> USAGE_POSITION
301 %token <regnum> USAGE_BLENDWEIGHT
302 %token <regnum> USAGE_BLENDINDICES
303 %token <regnum> USAGE_NORMAL
304 %token <regnum> USAGE_PSIZE
305 %token <regnum> USAGE_TEXCOORD
306 %token <regnum> USAGE_TANGENT
307 %token <regnum> USAGE_BINORMAL
308 %token <regnum> USAGE_TESSFACTOR
309 %token <regnum> USAGE_POSITIONT
310 %token <regnum> USAGE_COLOR
311 %token <regnum> USAGE_FOG
312 %token <regnum> USAGE_DEPTH
313 %token <regnum> USAGE_SAMPLE
315 /* Misc stuff */
316 %token <component> COMPONENT
317 %token <immval> IMMVAL
318 %token <immbool> IMMBOOL
320 %type <reg> dreg_name
321 %type <reg> dreg
322 %type <reg> sreg_name
323 %type <reg> relreg_name
324 %type <reg> sreg
325 %type <srcmod> smod
326 %type <writemask> writemask
327 %type <wm_components> wm_components
328 %type <swizzle> swizzle
329 %type <sw_components> sw_components
330 %type <modshift> omods
331 %type <modshift> omodifier
332 %type <comptype> comp
333 %type <declaration> dclusage
334 %type <reg> dcl_inputreg
335 %type <samplertype> sampdcl
336 %type <rel_reg> rel_reg
337 %type <reg> predicate
338 %type <immval> immsum
339 %type <sregs> sregs
343 shader: version_marker instructions
345 asm_ctx.funcs->end(&asm_ctx);
348 version_marker: VER_VS10
350 TRACE("Vertex shader 1.0\n");
351 create_vs10_parser(&asm_ctx);
353 | VER_VS11
355 TRACE("Vertex shader 1.1\n");
356 create_vs11_parser(&asm_ctx);
358 | VER_VS20
360 TRACE("Vertex shader 2.0\n");
361 create_vs20_parser(&asm_ctx);
363 | VER_VS2X
365 TRACE("Vertex shader 2.x\n");
366 create_vs2x_parser(&asm_ctx);
368 | VER_VS30
370 TRACE("Vertex shader 3.0\n");
371 create_vs30_parser(&asm_ctx);
373 | VER_PS10
375 TRACE("Pixel shader 1.0\n");
376 create_ps10_parser(&asm_ctx);
378 | VER_PS11
380 TRACE("Pixel shader 1.1\n");
381 create_ps11_parser(&asm_ctx);
383 | VER_PS12
385 TRACE("Pixel shader 1.2\n");
386 create_ps12_parser(&asm_ctx);
388 | VER_PS13
390 TRACE("Pixel shader 1.3\n");
391 create_ps13_parser(&asm_ctx);
393 | VER_PS14
395 TRACE("Pixel shader 1.4\n");
396 create_ps14_parser(&asm_ctx);
398 | VER_PS20
400 TRACE("Pixel shader 2.0\n");
401 create_ps20_parser(&asm_ctx);
403 | VER_PS2X
405 TRACE("Pixel shader 2.x\n");
406 create_ps2x_parser(&asm_ctx);
408 | VER_PS30
410 TRACE("Pixel shader 3.0\n");
411 create_ps30_parser(&asm_ctx);
414 instructions: /* empty */
415 | instructions complexinstr
417 /* Nothing to do */
420 complexinstr: instruction
424 | predicate instruction
426 TRACE("predicate\n");
427 asm_ctx.funcs->predicate(&asm_ctx, &$1);
429 | '+' instruction
431 TRACE("coissue\n");
432 asm_ctx.funcs->coissue(&asm_ctx);
435 instruction: INSTR_ADD omods dreg ',' sregs
437 TRACE("ADD\n");
438 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ADD, $2.mod, $2.shift, 0, &$3, &$5, 2);
440 | INSTR_NOP
442 TRACE("NOP\n");
443 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NOP, 0, 0, 0, 0, 0, 0);
445 | INSTR_MOV omods dreg ',' sregs
447 TRACE("MOV\n");
448 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOV, $2.mod, $2.shift, 0, &$3, &$5, 1);
450 | INSTR_SUB omods dreg ',' sregs
452 TRACE("SUB\n");
453 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SUB, $2.mod, $2.shift, 0, &$3, &$5, 2);
455 | INSTR_MAD omods dreg ',' sregs
457 TRACE("MAD\n");
458 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAD, $2.mod, $2.shift, 0, &$3, &$5, 3);
460 | INSTR_MUL omods dreg ',' sregs
462 TRACE("MUL\n");
463 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MUL, $2.mod, $2.shift, 0, &$3, &$5, 2);
465 | INSTR_RCP omods dreg ',' sregs
467 TRACE("RCP\n");
468 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RCP, $2.mod, $2.shift, 0, &$3, &$5, 1);
470 | INSTR_RSQ omods dreg ',' sregs
472 TRACE("RSQ\n");
473 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RSQ, $2.mod, $2.shift, 0, &$3, &$5, 1);
475 | INSTR_DP3 omods dreg ',' sregs
477 TRACE("DP3\n");
478 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP3, $2.mod, $2.shift, 0, &$3, &$5, 2);
480 | INSTR_DP4 omods dreg ',' sregs
482 TRACE("DP4\n");
483 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP4, $2.mod, $2.shift, 0, &$3, &$5, 2);
485 | INSTR_MIN omods dreg ',' sregs
487 TRACE("MIN\n");
488 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MIN, $2.mod, $2.shift, 0, &$3, &$5, 2);
490 | INSTR_MAX omods dreg ',' sregs
492 TRACE("MAX\n");
493 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAX, $2.mod, $2.shift, 0, &$3, &$5, 2);
495 | INSTR_SLT omods dreg ',' sregs
497 TRACE("SLT\n");
498 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SLT, $2.mod, $2.shift, 0, &$3, &$5, 2);
500 | INSTR_SGE omods dreg ',' sregs
502 TRACE("SGE\n");
503 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGE, $2.mod, $2.shift, 0, &$3, &$5, 2);
505 | INSTR_ABS omods dreg ',' sregs
507 TRACE("ABS\n");
508 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ABS, $2.mod, $2.shift, 0, &$3, &$5, 1);
510 | INSTR_EXP omods dreg ',' sregs
512 TRACE("EXP\n");
513 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXP, $2.mod, $2.shift, 0, &$3, &$5, 1);
515 | INSTR_LOG omods dreg ',' sregs
517 TRACE("LOG\n");
518 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOG, $2.mod, $2.shift, 0, &$3, &$5, 1);
520 | INSTR_LOGP omods dreg ',' sregs
522 TRACE("LOGP\n");
523 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOGP, $2.mod, $2.shift, 0, &$3, &$5, 1);
525 | INSTR_EXPP omods dreg ',' sregs
527 TRACE("EXPP\n");
528 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXPP, $2.mod, $2.shift, 0, &$3, &$5, 1);
530 | INSTR_DST omods dreg ',' sregs
532 TRACE("DST\n");
533 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DST, $2.mod, $2.shift, 0, &$3, &$5, 2);
535 | INSTR_LRP omods dreg ',' sregs
537 TRACE("LRP\n");
538 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LRP, $2.mod, $2.shift, 0, &$3, &$5, 3);
540 | INSTR_FRC omods dreg ',' sregs
542 TRACE("FRC\n");
543 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_FRC, $2.mod, $2.shift, 0, &$3, &$5, 1);
545 | INSTR_POW omods dreg ',' sregs
547 TRACE("POW\n");
548 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_POW, $2.mod, $2.shift, 0, &$3, &$5, 2);
550 | INSTR_CRS omods dreg ',' sregs
552 TRACE("CRS\n");
553 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CRS, $2.mod, $2.shift, 0, &$3, &$5, 2);
555 | INSTR_SGN omods dreg ',' sregs
557 TRACE("SGN\n");
558 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGN, $2.mod, $2.shift, 0, &$3, &$5, 3);
560 | INSTR_NRM omods dreg ',' sregs
562 TRACE("NRM\n");
563 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NRM, $2.mod, $2.shift, 0, &$3, &$5, 1);
565 | INSTR_SINCOS omods dreg ',' sregs
567 TRACE("SINCOS\n");
568 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SINCOS, $2.mod, $2.shift, 0, &$3, &$5, 1);
570 | INSTR_M4x4 omods dreg ',' sregs
572 TRACE("M4x4\n");
573 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
575 | INSTR_M4x3 omods dreg ',' sregs
577 TRACE("M4x3\n");
578 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
580 | INSTR_M3x4 omods dreg ',' sregs
582 TRACE("M3x4\n");
583 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
585 | INSTR_M3x3 omods dreg ',' sregs
587 TRACE("M3x3\n");
588 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
590 | INSTR_M3x2 omods dreg ',' sregs
592 TRACE("M3x2\n");
593 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x2, $2.mod, $2.shift, 0, &$3, &$5, 2);
595 | INSTR_DCL dclusage REG_OUTPUT
597 struct shader_reg reg;
598 TRACE("Output reg declaration\n");
599 ZeroMemory(&reg, sizeof(reg));
600 reg.type = BWRITERSPR_OUTPUT;
601 reg.regnum = $3;
602 reg.rel_reg = NULL;
603 reg.srcmod = 0;
604 reg.u.writemask = BWRITERSP_WRITEMASK_ALL;
605 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
607 | INSTR_DCL dclusage REG_OUTPUT writemask
609 struct shader_reg reg;
610 TRACE("Output reg declaration\n");
611 ZeroMemory(&reg, sizeof(reg));
612 reg.type = BWRITERSPR_OUTPUT;
613 reg.regnum = $3;
614 reg.rel_reg = NULL;
615 reg.srcmod = 0;
616 reg.u.writemask = $4;
617 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
619 | INSTR_DCL dclusage omods dcl_inputreg
621 struct shader_reg reg;
622 TRACE("Input reg declaration\n");
623 if($3.shift != 0) {
624 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
625 asm_ctx.line_no);
626 set_parse_status(&asm_ctx, PARSE_ERR);
628 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) ||
629 asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) {
630 asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n",
631 asm_ctx.line_no);
632 set_parse_status(&asm_ctx, PARSE_ERR);
634 ZeroMemory(&reg, sizeof(reg));
635 reg.type = $4.type;
636 reg.regnum = $4.regnum;
637 reg.rel_reg = NULL;
638 reg.srcmod = 0;
639 reg.u.writemask = BWRITERSP_WRITEMASK_ALL;
640 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, &reg);
642 | INSTR_DCL dclusage omods dcl_inputreg writemask
644 struct shader_reg reg;
645 TRACE("Input reg declaration\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 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) ||
652 asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) {
653 asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n",
654 asm_ctx.line_no);
655 set_parse_status(&asm_ctx, PARSE_ERR);
657 ZeroMemory(&reg, sizeof(reg));
658 reg.type = $4.type;
659 reg.regnum = $4.regnum;
660 reg.rel_reg = NULL;
661 reg.srcmod = 0;
662 reg.u.writemask = $5;
663 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, &reg);
665 | INSTR_DCL omods dcl_inputreg
667 struct shader_reg reg;
668 TRACE("Input reg declaration\n");
669 if($2.shift != 0) {
670 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
671 asm_ctx.line_no);
672 set_parse_status(&asm_ctx, PARSE_ERR);
674 if(asm_ctx.shader->type != ST_PIXEL) {
675 asmparser_message(&asm_ctx, "Line %u: Declaration needs a semantic\n",
676 asm_ctx.line_no);
677 set_parse_status(&asm_ctx, PARSE_ERR);
679 ZeroMemory(&reg, sizeof(reg));
680 reg.type = $3.type;
681 reg.regnum = $3.regnum;
682 reg.rel_reg = NULL;
683 reg.srcmod = 0;
684 reg.u.writemask = BWRITERSP_WRITEMASK_ALL;
685 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, &reg);
687 | INSTR_DCL omods dcl_inputreg writemask
689 struct shader_reg reg;
690 TRACE("Input reg declaration\n");
691 if($2.shift != 0) {
692 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
693 asm_ctx.line_no);
694 set_parse_status(&asm_ctx, PARSE_ERR);
696 if(asm_ctx.shader->type != ST_PIXEL) {
697 asmparser_message(&asm_ctx, "Line %u: Declaration needs a semantic\n",
698 asm_ctx.line_no);
699 set_parse_status(&asm_ctx, PARSE_ERR);
701 ZeroMemory(&reg, sizeof(reg));
702 reg.type = $3.type;
703 reg.regnum = $3.regnum;
704 reg.rel_reg = NULL;
705 reg.srcmod = 0;
706 reg.u.writemask = $4;
707 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, &reg);
709 | INSTR_DCL sampdcl omods REG_SAMPLER
711 TRACE("Sampler declared\n");
712 if($3.shift != 0) {
713 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
714 asm_ctx.line_no);
715 set_parse_status(&asm_ctx, PARSE_ERR);
717 asm_ctx.funcs->dcl_sampler(&asm_ctx, $2, $3.mod, $4, asm_ctx.line_no);
719 | INSTR_DCL omods REG_SAMPLER
721 TRACE("Sampler declared\n");
722 if($2.shift != 0) {
723 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n",
724 asm_ctx.line_no);
725 set_parse_status(&asm_ctx, PARSE_ERR);
727 if(asm_ctx.shader->type != ST_PIXEL) {
728 asmparser_message(&asm_ctx, "Line %u: Declaration needs a sampler type\n",
729 asm_ctx.line_no);
730 set_parse_status(&asm_ctx, PARSE_ERR);
732 asm_ctx.funcs->dcl_sampler(&asm_ctx, BWRITERSTT_UNKNOWN, $2.mod, $3, asm_ctx.line_no);
734 | INSTR_DCL sampdcl omods dcl_inputreg
736 TRACE("Error rule: sampler decl of input reg\n");
737 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of input regs is not valid\n",
738 asm_ctx.line_no);
739 set_parse_status(&asm_ctx, PARSE_WARN);
741 | INSTR_DCL sampdcl omods REG_OUTPUT
743 TRACE("Error rule: sampler decl of output reg\n");
744 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of output regs is not valid\n",
745 asm_ctx.line_no);
746 set_parse_status(&asm_ctx, PARSE_WARN);
748 | INSTR_DEF REG_CONSTFLOAT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
750 asm_ctx.funcs->constF(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val);
752 | INSTR_DEFI REG_CONSTINT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
754 asm_ctx.funcs->constI(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val);
756 | INSTR_DEFB REG_CONSTBOOL ',' IMMBOOL
758 asm_ctx.funcs->constB(&asm_ctx, $2, $4);
760 | INSTR_REP sregs
762 TRACE("REP\n");
763 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_REP, 0, 0, 0, 0, &$2, 1);
765 | INSTR_ENDREP
767 TRACE("ENDREP\n");
768 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDREP, 0, 0, 0, 0, 0, 0);
770 | INSTR_IF sregs
772 TRACE("IF\n");
773 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IF, 0, 0, 0, 0, &$2, 1);
775 | INSTR_IF comp sregs
777 TRACE("IFC\n");
778 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IFC, 0, 0, $2, 0, &$3, 2);
780 | INSTR_ELSE
782 TRACE("ELSE\n");
783 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ELSE, 0, 0, 0, 0, 0, 0);
785 | INSTR_ENDIF
787 TRACE("ENDIF\n");
788 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDIF, 0, 0, 0, 0, 0, 0);
790 | INSTR_BREAK
792 TRACE("BREAK\n");
793 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAK, 0, 0, 0, 0, 0, 0);
795 | INSTR_BREAK comp sregs
797 TRACE("BREAKC\n");
798 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKC, 0, 0, $2, 0, &$3, 2);
800 | INSTR_BREAKP sregs
802 TRACE("BREAKP\n");
803 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKP, 0, 0, 0, 0, &$2, 1);
805 | INSTR_CALL sregs
807 TRACE("CALL\n");
808 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALL, 0, 0, 0, 0, &$2, 1);
810 | INSTR_CALLNZ sregs
812 TRACE("CALLNZ\n");
813 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALLNZ, 0, 0, 0, 0, &$2, 2);
815 | INSTR_LOOP sregs
817 TRACE("LOOP\n");
818 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOOP, 0, 0, 0, 0, &$2, 2);
820 | INSTR_RET
822 TRACE("RET\n");
823 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RET, 0, 0, 0, 0, 0, 0);
825 | INSTR_ENDLOOP
827 TRACE("ENDLOOP\n");
828 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDLOOP, 0, 0, 0, 0, 0, 0);
830 | INSTR_LABEL sregs
832 TRACE("LABEL\n");
833 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LABEL, 0, 0, 0, 0, &$2, 1);
835 | INSTR_SETP comp dreg ',' sregs
837 TRACE("SETP\n");
838 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SETP, 0, 0, $2, &$3, &$5, 2);
840 | INSTR_TEXLDL omods dreg ',' sregs
842 TRACE("TEXLDL\n");
843 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDL, $2.mod, $2.shift, 0, &$3, &$5, 2);
845 | INSTR_LIT omods dreg ',' sregs
847 TRACE("LIT\n");
848 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LIT, $2.mod, $2.shift, 0, &$3, &$5, 1);
850 | INSTR_MOVA omods dreg ',' sregs
852 TRACE("MOVA\n");
853 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOVA, $2.mod, $2.shift, 0, &$3, &$5, 1);
855 | INSTR_CND omods dreg ',' sregs
857 TRACE("CND\n");
858 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CND, $2.mod, $2.shift, 0, &$3, &$5, 3);
860 | INSTR_CMP omods dreg ',' sregs
862 TRACE("CMP\n");
863 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CMP, $2.mod, $2.shift, 0, &$3, &$5, 3);
865 | INSTR_DP2ADD omods dreg ',' sregs
867 TRACE("DP2ADD\n");
868 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP2ADD, $2.mod, $2.shift, 0, &$3, &$5, 3);
870 | INSTR_TEXCOORD omods dreg
872 TRACE("TEXCOORD\n");
873 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXCOORD, $2.mod, $2.shift, 0, &$3, 0, 0);
875 | INSTR_TEXCRD omods dreg ',' sregs
877 TRACE("TEXCRD\n");
878 /* texcoord and texcrd share the same opcode */
879 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXCOORD, $2.mod, $2.shift, 0, &$3, &$5, 1);
881 | INSTR_TEXKILL dreg
883 TRACE("TEXKILL\n");
884 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXKILL, 0, 0, 0, &$2, 0, 0);
886 | INSTR_TEX omods dreg
888 TRACE("TEX\n");
889 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, 0, 0);
891 | INSTR_TEXDEPTH omods dreg
893 TRACE("TEXDEPTH\n");
894 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDEPTH, $2.mod, $2.shift, 0, &$3, 0, 0);
896 | INSTR_TEXLD omods dreg ',' sregs
898 TRACE("TEXLD\n");
899 /* There is more than one acceptable syntax for texld:
900 with 1 sreg (PS 1.4) or
901 with 2 sregs (PS 2.0+)
902 Moreover, texld shares the same opcode as the tex instruction,
903 so there are a total of 3 valid syntaxes
904 These variations are handled in asmparser.c */
905 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, &$5, 2);
907 | INSTR_TEXLDP omods dreg ',' sregs
909 TRACE("TEXLDP\n");
910 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDP, $2.mod, $2.shift, 0, &$3, &$5, 2);
912 | INSTR_TEXLDB omods dreg ',' sregs
914 TRACE("TEXLDB\n");
915 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDB, $2.mod, $2.shift, 0, &$3, &$5, 2);
917 | INSTR_TEXBEM omods dreg ',' sregs
919 TRACE("TEXBEM\n");
920 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXBEM, $2.mod, $2.shift, 0, &$3, &$5, 1);
922 | INSTR_TEXBEML omods dreg ',' sregs
924 TRACE("TEXBEML\n");
925 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXBEML, $2.mod, $2.shift, 0, &$3, &$5, 1);
927 | INSTR_TEXREG2AR omods dreg ',' sregs
929 TRACE("TEXREG2AR\n");
930 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2AR, $2.mod, $2.shift, 0, &$3, &$5, 1);
932 | INSTR_TEXREG2GB omods dreg ',' sregs
934 TRACE("TEXREG2GB\n");
935 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2GB, $2.mod, $2.shift, 0, &$3, &$5, 1);
937 | INSTR_TEXREG2RGB omods dreg ',' sregs
939 TRACE("TEXREG2RGB\n");
940 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2RGB, $2.mod, $2.shift, 0, &$3, &$5, 1);
942 | INSTR_TEXM3x2PAD omods dreg ',' sregs
944 TRACE("TEXM3x2PAD\n");
945 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2PAD, $2.mod, $2.shift, 0, &$3, &$5, 1);
947 | INSTR_TEXM3x3PAD omods dreg ',' sregs
949 TRACE("INSTR_TEXM3x3PAD\n");
950 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3PAD, $2.mod, $2.shift, 0, &$3, &$5, 1);
952 | INSTR_TEXM3x3SPEC omods dreg ',' sregs
954 TRACE("TEXM3x3SPEC\n");
955 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3SPEC, $2.mod, $2.shift, 0, &$3, &$5, 2);
957 | INSTR_TEXM3x3VSPEC omods dreg ',' sregs
959 TRACE("TEXM3x3VSPEC\n");
960 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3VSPEC, $2.mod, $2.shift, 0, &$3, &$5, 1);
962 | INSTR_TEXM3x3TEX omods dreg ',' sregs
964 TRACE("TEXM3x3TEX\n");
965 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3TEX, $2.mod, $2.shift, 0, &$3, &$5, 1);
967 | INSTR_TEXDP3TEX omods dreg ',' sregs
969 TRACE("TEXDP3TEX\n");
970 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDP3TEX, $2.mod, $2.shift, 0, &$3, &$5, 1);
972 | INSTR_TEXM3x2DEPTH omods dreg ',' sregs
974 TRACE("TEXM3x2DEPTH\n");
975 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2DEPTH, $2.mod, $2.shift, 0, &$3, &$5, 1);
977 | INSTR_TEXM3x2TEX omods dreg ',' sregs
979 TRACE("TEXM3x2TEX\n");
980 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2TEX, $2.mod, $2.shift, 0, &$3, &$5, 1);
982 | INSTR_TEXDP3 omods dreg ',' sregs
984 TRACE("TEXDP3\n");
985 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDP3, $2.mod, $2.shift, 0, &$3, &$5, 1);
987 | INSTR_TEXM3x3 omods dreg ',' sregs
989 TRACE("TEXM3x3\n");
990 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3, $2.mod, $2.shift, 0, &$3, &$5, 1);
992 | INSTR_BEM omods dreg ',' sregs
994 TRACE("BEM\n");
995 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BEM, $2.mod, $2.shift, 0, &$3, &$5, 2);
997 | INSTR_DSX omods dreg ',' sregs
999 TRACE("DSX\n");
1000 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSX, $2.mod, $2.shift, 0, &$3, &$5, 1);
1002 | INSTR_DSY omods dreg ',' sregs
1004 TRACE("DSY\n");
1005 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSY, $2.mod, $2.shift, 0, &$3, &$5, 1);
1007 | INSTR_TEXLDD omods dreg ',' sregs
1009 TRACE("TEXLDD\n");
1010 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDD, $2.mod, $2.shift, 0, &$3, &$5, 4);
1012 | INSTR_PHASE
1014 TRACE("PHASE\n");
1015 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_PHASE, 0, 0, 0, 0, 0, 0);
1019 dreg: dreg_name rel_reg
1021 $$.regnum = $1.regnum;
1022 $$.type = $1.type;
1023 $$.u.writemask = BWRITERSP_WRITEMASK_ALL;
1024 $$.srcmod = BWRITERSPSM_NONE;
1025 set_rel_reg(&$$, &$2);
1027 | dreg_name writemask
1029 $$.regnum = $1.regnum;
1030 $$.type = $1.type;
1031 $$.u.writemask = $2;
1032 $$.srcmod = BWRITERSPSM_NONE;
1033 $$.rel_reg = NULL;
1036 dreg_name: REG_TEMP
1038 $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
1040 | REG_OUTPUT
1042 $$.regnum = $1; $$.type = BWRITERSPR_OUTPUT;
1044 | REG_INPUT
1046 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1048 | REG_CONSTFLOAT
1050 asmparser_message(&asm_ctx, "Line %u: Register c%u is not a valid destination register\n",
1051 asm_ctx.line_no, $1);
1052 set_parse_status(&asm_ctx, PARSE_WARN);
1054 | REG_CONSTINT
1056 asmparser_message(&asm_ctx, "Line %u: Register i%u is not a valid destination register\n",
1057 asm_ctx.line_no, $1);
1058 set_parse_status(&asm_ctx, PARSE_WARN);
1060 | REG_CONSTBOOL
1062 asmparser_message(&asm_ctx, "Line %u: Register b%u is not a valid destination register\n",
1063 asm_ctx.line_no, $1);
1064 set_parse_status(&asm_ctx, PARSE_WARN);
1066 | REG_TEXTURE
1068 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1070 | REG_TEXCRDOUT
1072 $$.regnum = $1; $$.type = BWRITERSPR_TEXCRDOUT;
1074 | REG_SAMPLER
1076 asmparser_message(&asm_ctx, "Line %u: Register s%u is not a valid destination register\n",
1077 asm_ctx.line_no, $1);
1078 set_parse_status(&asm_ctx, PARSE_WARN);
1080 | REG_OPOS
1082 $$.regnum = BWRITERSRO_POSITION; $$.type = BWRITERSPR_RASTOUT;
1084 | REG_OPTS
1086 $$.regnum = BWRITERSRO_POINT_SIZE; $$.type = BWRITERSPR_RASTOUT;
1088 | REG_OFOG
1090 $$.regnum = BWRITERSRO_FOG; $$.type = BWRITERSPR_RASTOUT;
1092 | REG_VERTEXCOLOR
1094 $$.regnum = $1; $$.type = BWRITERSPR_ATTROUT;
1096 | REG_FRAGCOLOR
1098 $$.regnum = $1; $$.type = BWRITERSPR_COLOROUT;
1100 | REG_FRAGDEPTH
1102 $$.regnum = 0; $$.type = BWRITERSPR_DEPTHOUT;
1104 | REG_PREDICATE
1106 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
1108 | REG_VPOS
1110 asmparser_message(&asm_ctx, "Line %u: Register vPos is not a valid destination register\n",
1111 asm_ctx.line_no);
1112 set_parse_status(&asm_ctx, PARSE_WARN);
1114 | REG_VFACE
1116 asmparser_message(&asm_ctx, "Line %u: Register vFace is not a valid destination register\n",
1117 asm_ctx.line_no);
1118 set_parse_status(&asm_ctx, PARSE_WARN);
1120 | REG_ADDRESS
1122 /* index 0 is hardcoded for the addr register */
1123 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1125 | REG_LOOP
1127 asmparser_message(&asm_ctx, "Line %u: Register aL is not a valid destination register\n",
1128 asm_ctx.line_no);
1129 set_parse_status(&asm_ctx, PARSE_WARN);
1132 writemask: '.' wm_components
1134 if($2.writemask == SWIZZLE_ERR) {
1135 asmparser_message(&asm_ctx, "Line %u: Invalid writemask specified\n",
1136 asm_ctx.line_no);
1137 set_parse_status(&asm_ctx, PARSE_ERR);
1138 /* Provide a correct writemask to prevent following complaints */
1139 $$ = BWRITERSP_WRITEMASK_ALL;
1141 else {
1142 $$ = $2.writemask;
1143 TRACE("Writemask: %x\n", $$);
1147 wm_components: COMPONENT
1149 $$.writemask = 1 << $1;
1150 $$.last = $1;
1151 $$.idx = 1;
1153 | wm_components COMPONENT
1155 if($1.writemask == SWIZZLE_ERR || $1.idx == 4)
1156 /* Wrong writemask */
1157 $$.writemask = SWIZZLE_ERR;
1158 else {
1159 if($2 <= $1.last)
1160 $$.writemask = SWIZZLE_ERR;
1161 else {
1162 $$.writemask = $1.writemask | (1 << $2);
1163 $$.idx = $1.idx + 1;
1168 swizzle: /* empty */
1170 $$ = BWRITERVS_NOSWIZZLE;
1171 TRACE("Default swizzle: %08x\n", $$);
1173 | '.' sw_components
1175 if($2.swizzle == SWIZZLE_ERR) {
1176 asmparser_message(&asm_ctx, "Line %u: Invalid swizzle\n",
1177 asm_ctx.line_no);
1178 set_parse_status(&asm_ctx, PARSE_ERR);
1179 /* Provide a correct swizzle to prevent following complaints */
1180 $$ = BWRITERVS_NOSWIZZLE;
1182 else {
1183 DWORD last, i;
1185 $$ = $2.swizzle << BWRITERVS_SWIZZLE_SHIFT;
1186 /* Fill the swizzle by extending the last component */
1187 last = ($2.swizzle >> 2 * ($2.idx - 1)) & 0x03;
1188 for(i = $2.idx; i < 4; i++){
1189 $$ |= last << (BWRITERVS_SWIZZLE_SHIFT + 2 * i);
1191 TRACE("Got a swizzle: %08x\n", $$);
1195 sw_components: COMPONENT
1197 $$.swizzle = $1;
1198 $$.idx = 1;
1200 | sw_components COMPONENT
1202 if($1.idx == 4) {
1203 /* Too many sw_components */
1204 $$.swizzle = SWIZZLE_ERR;
1205 $$.idx = 4;
1207 else {
1208 $$.swizzle = $1.swizzle | ($2 << 2 * $1.idx);
1209 $$.idx = $1.idx + 1;
1213 omods: /* Empty */
1215 $$.mod = 0;
1216 $$.shift = 0;
1218 | omods omodifier
1220 $$.mod = $1.mod | $2.mod;
1221 if($1.shift && $2.shift) {
1222 asmparser_message(&asm_ctx, "Line %u: More than one shift flag\n",
1223 asm_ctx.line_no);
1224 set_parse_status(&asm_ctx, PARSE_ERR);
1225 $$.shift = $1.shift;
1226 } else {
1227 $$.shift = $1.shift | $2.shift;
1231 omodifier: SHIFT_X2
1233 $$.mod = 0;
1234 $$.shift = 1;
1236 | SHIFT_X4
1238 $$.mod = 0;
1239 $$.shift = 2;
1241 | SHIFT_X8
1243 $$.mod = 0;
1244 $$.shift = 3;
1246 | SHIFT_D2
1248 $$.mod = 0;
1249 $$.shift = 15;
1251 | SHIFT_D4
1253 $$.mod = 0;
1254 $$.shift = 14;
1256 | SHIFT_D8
1258 $$.mod = 0;
1259 $$.shift = 13;
1261 | MOD_SAT
1263 $$.mod = BWRITERSPDM_SATURATE;
1264 $$.shift = 0;
1266 | MOD_PP
1268 $$.mod = BWRITERSPDM_PARTIALPRECISION;
1269 $$.shift = 0;
1271 | MOD_CENTROID
1273 $$.mod = BWRITERSPDM_MSAMPCENTROID;
1274 $$.shift = 0;
1277 sregs: sreg
1279 $$.reg[0] = $1;
1280 $$.count = 1;
1282 | sregs ',' sreg
1284 if($$.count == MAX_SRC_REGS){
1285 asmparser_message(&asm_ctx, "Line %u: Too many source registers in this instruction\n",
1286 asm_ctx.line_no);
1287 set_parse_status(&asm_ctx, PARSE_ERR);
1289 else
1290 $$.reg[$$.count++] = $3;
1293 sreg: sreg_name rel_reg swizzle
1295 $$.type = $1.type;
1296 $$.regnum = $1.regnum;
1297 $$.u.swizzle = $3;
1298 $$.srcmod = BWRITERSPSM_NONE;
1299 set_rel_reg(&$$, &$2);
1301 | sreg_name rel_reg smod swizzle
1303 $$.type = $1.type;
1304 $$.regnum = $1.regnum;
1305 set_rel_reg(&$$, &$2);
1306 $$.srcmod = $3;
1307 $$.u.swizzle = $4;
1309 | '-' sreg_name rel_reg swizzle
1311 $$.type = $2.type;
1312 $$.regnum = $2.regnum;
1313 $$.srcmod = BWRITERSPSM_NEG;
1314 set_rel_reg(&$$, &$3);
1315 $$.u.swizzle = $4;
1317 | '-' sreg_name rel_reg smod swizzle
1319 $$.type = $2.type;
1320 $$.regnum = $2.regnum;
1321 set_rel_reg(&$$, &$3);
1322 switch($4) {
1323 case BWRITERSPSM_BIAS: $$.srcmod = BWRITERSPSM_BIASNEG; break;
1324 case BWRITERSPSM_X2: $$.srcmod = BWRITERSPSM_X2NEG; break;
1325 case BWRITERSPSM_SIGN: $$.srcmod = BWRITERSPSM_SIGNNEG; break;
1326 case BWRITERSPSM_ABS: $$.srcmod = BWRITERSPSM_ABSNEG; break;
1327 case BWRITERSPSM_DZ:
1328 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DZ\n",
1329 asm_ctx.line_no);
1330 set_parse_status(&asm_ctx, PARSE_ERR);
1331 break;
1332 case BWRITERSPSM_DW:
1333 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DW\n",
1334 asm_ctx.line_no);
1335 set_parse_status(&asm_ctx, PARSE_ERR);
1336 break;
1337 default:
1338 FIXME("Unhandled combination of NEGATE and %u\n", $4);
1340 $$.u.swizzle = $5;
1342 | IMMVAL '-' sreg_name rel_reg swizzle
1344 if($1.val != 1.0 || (!$1.integer)) {
1345 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP, "
1346 "%g - reg found\n", asm_ctx.line_no, $1.val);
1347 set_parse_status(&asm_ctx, PARSE_ERR);
1349 /* Complement - not compatible with other source modifiers */
1350 $$.type = $3.type;
1351 $$.regnum = $3.regnum;
1352 $$.srcmod = BWRITERSPSM_COMP;
1353 set_rel_reg(&$$, &$4);
1354 $$.u.swizzle = $5;
1356 | IMMVAL '-' sreg_name rel_reg smod swizzle
1358 /* For nicer error reporting */
1359 if($1.val != 1.0 || (!$1.integer)) {
1360 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP\n",
1361 asm_ctx.line_no);
1362 set_parse_status(&asm_ctx, PARSE_ERR);
1363 } else {
1364 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: D3DSPSM_COMP and %s\n",
1365 asm_ctx.line_no,
1366 debug_print_srcmod($5));
1367 set_parse_status(&asm_ctx, PARSE_ERR);
1370 | SMOD_NOT sreg_name swizzle
1372 $$.type = $2.type;
1373 $$.regnum = $2.regnum;
1374 $$.rel_reg = NULL;
1375 $$.srcmod = BWRITERSPSM_NOT;
1376 $$.u.swizzle = $3;
1379 rel_reg: /* empty */
1381 $$.has_rel_reg = FALSE;
1382 $$.additional_offset = 0;
1384 | '[' immsum ']'
1386 $$.has_rel_reg = FALSE;
1387 $$.additional_offset = $2.val;
1389 | '[' relreg_name swizzle ']'
1391 $$.has_rel_reg = TRUE;
1392 $$.type = $2.type;
1393 $$.additional_offset = 0;
1394 $$.rel_regnum = $2.regnum;
1395 $$.swizzle = $3;
1397 | '[' immsum '+' relreg_name swizzle ']'
1399 $$.has_rel_reg = TRUE;
1400 $$.type = $4.type;
1401 $$.additional_offset = $2.val;
1402 $$.rel_regnum = $4.regnum;
1403 $$.swizzle = $5;
1405 | '[' relreg_name swizzle '+' immsum ']'
1407 $$.has_rel_reg = TRUE;
1408 $$.type = $2.type;
1409 $$.additional_offset = $5.val;
1410 $$.rel_regnum = $2.regnum;
1411 $$.swizzle = $3;
1413 | '[' immsum '+' relreg_name swizzle '+' immsum ']'
1415 $$.has_rel_reg = TRUE;
1416 $$.type = $4.type;
1417 $$.additional_offset = $2.val + $7.val;
1418 $$.rel_regnum = $4.regnum;
1419 $$.swizzle = $5;
1422 immsum: IMMVAL
1424 if(!$1.integer) {
1425 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1426 asm_ctx.line_no, $1.val);
1427 set_parse_status(&asm_ctx, PARSE_ERR);
1429 $$.val = $1.val;
1431 | immsum '+' IMMVAL
1433 if(!$3.integer) {
1434 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
1435 asm_ctx.line_no, $3.val);
1436 set_parse_status(&asm_ctx, PARSE_ERR);
1438 $$.val = $1.val + $3.val;
1441 smod: SMOD_BIAS
1443 $$ = BWRITERSPSM_BIAS;
1445 | SHIFT_X2
1447 $$ = BWRITERSPSM_X2;
1449 | SMOD_SCALEBIAS
1451 $$ = BWRITERSPSM_SIGN;
1453 | SMOD_DZ
1455 $$ = BWRITERSPSM_DZ;
1457 | SMOD_DW
1459 $$ = BWRITERSPSM_DW;
1461 | SMOD_ABS
1463 $$ = BWRITERSPSM_ABS;
1466 relreg_name: REG_ADDRESS
1468 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1470 | REG_LOOP
1472 $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1475 sreg_name: REG_TEMP
1477 $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
1479 | REG_OUTPUT
1481 asmparser_message(&asm_ctx, "Line %u: Register o%u is not a valid source register\n",
1482 asm_ctx.line_no, $1);
1483 set_parse_status(&asm_ctx, PARSE_WARN);
1485 | REG_INPUT
1487 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1489 | REG_CONSTFLOAT
1491 $$.regnum = $1; $$.type = BWRITERSPR_CONST;
1493 | REG_CONSTINT
1495 $$.regnum = $1; $$.type = BWRITERSPR_CONSTINT;
1497 | REG_CONSTBOOL
1499 $$.regnum = $1; $$.type = BWRITERSPR_CONSTBOOL;
1501 | REG_TEXTURE
1503 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1505 | REG_TEXCRDOUT
1507 asmparser_message(&asm_ctx, "Line %u: Register oT%u is not a valid source register\n",
1508 asm_ctx.line_no, $1);
1509 set_parse_status(&asm_ctx, PARSE_WARN);
1511 | REG_SAMPLER
1513 $$.regnum = $1; $$.type = BWRITERSPR_SAMPLER;
1515 | REG_OPOS
1517 asmparser_message(&asm_ctx, "Line %u: Register oPos is not a valid source register\n",
1518 asm_ctx.line_no);
1519 set_parse_status(&asm_ctx, PARSE_WARN);
1521 | REG_OFOG
1523 asmparser_message(&asm_ctx, "Line %u: Register oFog is not a valid source register\n",
1524 asm_ctx.line_no);
1525 set_parse_status(&asm_ctx, PARSE_WARN);
1527 | REG_VERTEXCOLOR
1529 asmparser_message(&asm_ctx, "Line %u: Register oD%u is not a valid source register\n",
1530 asm_ctx.line_no, $1);
1531 set_parse_status(&asm_ctx, PARSE_WARN);
1533 | REG_FRAGCOLOR
1535 asmparser_message(&asm_ctx, "Line %u: Register oC%u is not a valid source register\n",
1536 asm_ctx.line_no, $1);
1537 set_parse_status(&asm_ctx, PARSE_WARN);
1539 | REG_FRAGDEPTH
1541 asmparser_message(&asm_ctx, "Line %u: Register oDepth is not a valid source register\n",
1542 asm_ctx.line_no);
1543 set_parse_status(&asm_ctx, PARSE_WARN);
1545 | REG_PREDICATE
1547 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
1549 | REG_VPOS
1551 $$.regnum = 0; $$.type = BWRITERSPR_MISCTYPE;
1553 | REG_VFACE
1555 $$.regnum = 1; $$.type = BWRITERSPR_MISCTYPE;
1557 | REG_ADDRESS
1559 $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
1561 | REG_LOOP
1563 $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
1565 | REG_LABEL
1567 $$.regnum = $1; $$.type = BWRITERSPR_LABEL;
1570 comp: COMP_GT { $$ = BWRITER_COMPARISON_GT; }
1571 | COMP_LT { $$ = BWRITER_COMPARISON_LT; }
1572 | COMP_GE { $$ = BWRITER_COMPARISON_GE; }
1573 | COMP_LE { $$ = BWRITER_COMPARISON_LE; }
1574 | COMP_EQ { $$ = BWRITER_COMPARISON_EQ; }
1575 | COMP_NE { $$ = BWRITER_COMPARISON_NE; }
1577 dclusage: USAGE_POSITION
1579 TRACE("dcl_position%u\n", $1);
1580 $$.regnum = $1;
1581 $$.dclusage = BWRITERDECLUSAGE_POSITION;
1583 | USAGE_BLENDWEIGHT
1585 TRACE("dcl_blendweight%u\n", $1);
1586 $$.regnum = $1;
1587 $$.dclusage = BWRITERDECLUSAGE_BLENDWEIGHT;
1589 | USAGE_BLENDINDICES
1591 TRACE("dcl_blendindices%u\n", $1);
1592 $$.regnum = $1;
1593 $$.dclusage = BWRITERDECLUSAGE_BLENDINDICES;
1595 | USAGE_NORMAL
1597 TRACE("dcl_normal%u\n", $1);
1598 $$.regnum = $1;
1599 $$.dclusage = BWRITERDECLUSAGE_NORMAL;
1601 | USAGE_PSIZE
1603 TRACE("dcl_psize%u\n", $1);
1604 $$.regnum = $1;
1605 $$.dclusage = BWRITERDECLUSAGE_PSIZE;
1607 | USAGE_TEXCOORD
1609 TRACE("dcl_texcoord%u\n", $1);
1610 $$.regnum = $1;
1611 $$.dclusage = BWRITERDECLUSAGE_TEXCOORD;
1613 | USAGE_TANGENT
1615 TRACE("dcl_tangent%u\n", $1);
1616 $$.regnum = $1;
1617 $$.dclusage = BWRITERDECLUSAGE_TANGENT;
1619 | USAGE_BINORMAL
1621 TRACE("dcl_binormal%u\n", $1);
1622 $$.regnum = $1;
1623 $$.dclusage = BWRITERDECLUSAGE_BINORMAL;
1625 | USAGE_TESSFACTOR
1627 TRACE("dcl_tessfactor%u\n", $1);
1628 $$.regnum = $1;
1629 $$.dclusage = BWRITERDECLUSAGE_TESSFACTOR;
1631 | USAGE_POSITIONT
1633 TRACE("dcl_positiont%u\n", $1);
1634 $$.regnum = $1;
1635 $$.dclusage = BWRITERDECLUSAGE_POSITIONT;
1637 | USAGE_COLOR
1639 TRACE("dcl_color%u\n", $1);
1640 $$.regnum = $1;
1641 $$.dclusage = BWRITERDECLUSAGE_COLOR;
1643 | USAGE_FOG
1645 TRACE("dcl_fog%u\n", $1);
1646 $$.regnum = $1;
1647 $$.dclusage = BWRITERDECLUSAGE_FOG;
1649 | USAGE_DEPTH
1651 TRACE("dcl_depth%u\n", $1);
1652 $$.regnum = $1;
1653 $$.dclusage = BWRITERDECLUSAGE_DEPTH;
1655 | USAGE_SAMPLE
1657 TRACE("dcl_sample%u\n", $1);
1658 $$.regnum = $1;
1659 $$.dclusage = BWRITERDECLUSAGE_SAMPLE;
1662 dcl_inputreg: REG_INPUT
1664 $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
1666 | REG_TEXTURE
1668 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
1671 sampdcl: SAMPTYPE_1D
1673 $$ = BWRITERSTT_1D;
1675 | SAMPTYPE_2D
1677 $$ = BWRITERSTT_2D;
1679 | SAMPTYPE_CUBE
1681 $$ = BWRITERSTT_CUBE;
1683 | SAMPTYPE_VOLUME
1685 $$ = BWRITERSTT_VOLUME;
1688 predicate: '(' REG_PREDICATE swizzle ')'
1690 $$.type = BWRITERSPR_PREDICATE;
1691 $$.regnum = 0;
1692 $$.rel_reg = NULL;
1693 $$.srcmod = BWRITERSPSM_NONE;
1694 $$.u.swizzle = $3;
1696 | '(' SMOD_NOT REG_PREDICATE swizzle ')'
1698 $$.type = BWRITERSPR_PREDICATE;
1699 $$.regnum = 0;
1700 $$.rel_reg = NULL;
1701 $$.srcmod = BWRITERSPSM_NOT;
1702 $$.u.swizzle = $4;
1707 /* New status is the worst between current status and parameter value */
1708 void set_parse_status(struct asm_parser *ctx, enum parse_status status) {
1709 if(status == PARSE_ERR) ctx->status = PARSE_ERR;
1710 else if(status == PARSE_WARN && ctx->status == PARSE_SUCCESS) ctx->status = PARSE_WARN;
1713 struct bwriter_shader *parse_asm_shader(char **messages) {
1714 struct bwriter_shader *ret = NULL;
1716 asm_ctx.shader = NULL;
1717 asm_ctx.status = PARSE_SUCCESS;
1718 asm_ctx.messagesize = asm_ctx.messagecapacity = 0;
1719 asm_ctx.line_no = 1;
1721 asmshader_parse();
1723 if(asm_ctx.status != PARSE_ERR) ret = asm_ctx.shader;
1724 else if(asm_ctx.shader) SlDeleteShader(asm_ctx.shader);
1726 if(messages) {
1727 if(asm_ctx.messagesize) {
1728 /* Shrink the buffer to the used size */
1729 *messages = asm_realloc(asm_ctx.messages, asm_ctx.messagesize + 1);
1730 if(!*messages) {
1731 ERR("Out of memory, no messages reported\n");
1732 asm_free(asm_ctx.messages);
1734 } else {
1735 *messages = NULL;
1737 } else {
1738 if(asm_ctx.messagecapacity) asm_free(asm_ctx.messages);
1741 return ret;