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
24 #include "wine/port.h"
25 #include "wine/debug.h"
27 #include "d3dx9_36_private.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
42 reg
->regnum
+= rel
->additional_offset
;
43 if
(!rel
->has_rel_reg
) {
46 reg
->rel_reg
= asm_alloc
(sizeof
(*reg
->rel_reg
));
50 reg
->rel_reg
->type
= rel
->type
;
51 reg
->rel_reg
->swizzle
= rel
->swizzle
;
52 reg
->rel_reg
->regnum
= rel
->rel_regnum
;
65 struct shader_reg reg
;
83 BWRITER_COMPARISON_TYPE comptype
;
88 BWRITERSAMPLER_TEXTURE_TYPE samplertype
;
89 struct rel_reg rel_reg
;
90 struct src_regs sregs
;
93 /* Common instructions between vertex and pixel shaders */
146 /* Vertex shader only instructions */
150 /* Pixel shader only instructions */
162 %token
<regnum
> REG_TEMP
163 %token
<regnum
> REG_OUTPUT
164 %token
<regnum
> REG_INPUT
165 %token
<regnum
> REG_CONSTFLOAT
166 %token
<regnum
> REG_CONSTINT
167 %token
<regnum
> REG_CONSTBOOL
168 %token
<regnum
> REG_TEXTURE
169 %token
<regnum
> REG_SAMPLER
170 %token
<regnum
> REG_TEXCRDOUT
174 %token
<regnum
> REG_VERTEXCOLOR
175 %token
<regnum
> REG_FRAGCOLOR
182 %token
<regnum
> REG_LABEL
200 /* Output modifiers */
219 /* Source register modifiers */
221 %token SMOD_SCALEBIAS
231 %token SAMPTYPE_VOLUME
233 /* Usage declaration tokens */
234 %token
<regnum
> USAGE_POSITION
235 %token
<regnum
> USAGE_BLENDWEIGHT
236 %token
<regnum
> USAGE_BLENDINDICES
237 %token
<regnum
> USAGE_NORMAL
238 %token
<regnum
> USAGE_PSIZE
239 %token
<regnum
> USAGE_TEXCOORD
240 %token
<regnum
> USAGE_TANGENT
241 %token
<regnum
> USAGE_BINORMAL
242 %token
<regnum
> USAGE_TESSFACTOR
243 %token
<regnum
> USAGE_POSITIONT
244 %token
<regnum
> USAGE_COLOR
245 %token
<regnum
> USAGE_FOG
246 %token
<regnum
> USAGE_DEPTH
247 %token
<regnum
> USAGE_SAMPLE
250 %token
<component
> COMPONENT
251 %token
<immval
> IMMVAL
252 %token
<immbool
> IMMBOOL
254 %type
<reg
> dreg_name
256 %type
<reg
> sreg_name
257 %type
<reg
> relreg_name
260 %type
<writemask
> writemask
261 %type
<wm_components
> wm_components
262 %type
<swizzle
> swizzle
263 %type
<sw_components
> sw_components
264 %type
<modshift
> omods
265 %type
<modshift
> omodifier
266 %type
<comptype
> comp
267 %type
<declaration
> dclusage
268 %type
<reg
> dcl_inputreg
269 %type
<samplertype
> sampdcl
270 %type
<rel_reg
> rel_reg
271 %type
<reg
> predicate
272 %type
<immval
> immsum
277 shader: version_marker instructions
279 asm_ctx.funcs
->end
(&asm_ctx
);
282 version_marker: VER_VS10
284 TRACE
("Vertex shader 1.0\n");
285 create_vs10_parser
(&asm_ctx
);
289 TRACE
("Vertex shader 1.1\n");
290 create_vs11_parser
(&asm_ctx
);
294 TRACE
("Vertex shader 2.0\n");
295 create_vs20_parser
(&asm_ctx
);
299 TRACE
("Vertex shader 2.x\n");
300 create_vs2x_parser
(&asm_ctx
);
304 TRACE
("Vertex shader 3.0\n");
305 create_vs30_parser
(&asm_ctx
);
309 TRACE
("Pixel shader 1.0\n");
310 set_parse_status
(&asm_ctx
, PARSE_ERR
);
315 TRACE
("Pixel shader 1.1\n");
316 set_parse_status
(&asm_ctx
, PARSE_ERR
);
321 TRACE
("Pixel shader 1.2\n");
322 set_parse_status
(&asm_ctx
, PARSE_ERR
);
327 TRACE
("Pixel shader 1.3\n");
328 set_parse_status
(&asm_ctx
, PARSE_ERR
);
333 TRACE
("Pixel shader 1.4\n");
334 set_parse_status
(&asm_ctx
, PARSE_ERR
);
339 TRACE
("Pixel shader 2.0\n");
340 create_ps20_parser
(&asm_ctx
);
344 TRACE
("Pixel shader 2.x\n");
345 create_ps2x_parser
(&asm_ctx
);
349 TRACE
("Pixel shader 3.0\n");
350 create_ps30_parser
(&asm_ctx
);
353 instructions: /* empty */
354 | instructions complexinstr
359 complexinstr: instruction
363 | predicate instruction
365 TRACE
("predicate\n");
366 asm_ctx.funcs
->predicate
(&asm_ctx
, &$1);
369 instruction: INSTR_ADD omods dreg
',' sregs
372 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ADD
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
377 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_NOP
, 0, 0, 0, 0, 0, 0);
379 | INSTR_MOV omods dreg
',' sregs
382 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MOV
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
384 | INSTR_SUB omods dreg
',' sregs
387 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SUB
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
389 | INSTR_MAD omods dreg
',' sregs
392 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MAD
, $2.mod
, $2.shift
, 0, &$3, &$5, 3);
394 | INSTR_MUL omods dreg
',' sregs
397 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MUL
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
399 | INSTR_RCP omods dreg
',' sregs
402 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_RCP
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
404 | INSTR_RSQ omods dreg
',' sregs
407 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_RSQ
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
409 | INSTR_DP3 omods dreg
',' sregs
412 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_DP3
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
414 | INSTR_DP4 omods dreg
',' sregs
417 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_DP4
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
419 | INSTR_MIN omods dreg
',' sregs
422 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MIN
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
424 | INSTR_MAX omods dreg
',' sregs
427 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MAX
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
429 | INSTR_SLT omods dreg
',' sregs
432 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SLT
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
434 | INSTR_SGE omods dreg
',' sregs
437 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SGE
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
439 | INSTR_ABS omods dreg
',' sregs
442 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ABS
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
444 | INSTR_EXP omods dreg
',' sregs
447 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_EXP
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
449 | INSTR_LOG omods dreg
',' sregs
452 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LOG
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
454 | INSTR_LOGP omods dreg
',' sregs
457 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LOGP
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
459 | INSTR_EXPP omods dreg
',' sregs
462 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_EXPP
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
464 | INSTR_DST omods dreg
',' sregs
467 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_DST
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
469 | INSTR_LRP omods dreg
',' sregs
472 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LRP
, $2.mod
, $2.shift
, 0, &$3, &$5, 3);
474 | INSTR_FRC omods dreg
',' sregs
477 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_FRC
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
479 | INSTR_POW omods dreg
',' sregs
482 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_POW
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
484 | INSTR_CRS omods dreg
',' sregs
487 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_CRS
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
489 | INSTR_SGN omods dreg
',' sregs
492 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SGN
, $2.mod
, $2.shift
, 0, &$3, &$5, 3);
494 | INSTR_NRM omods dreg
',' sregs
497 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_NRM
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
499 | INSTR_SINCOS omods dreg
',' sregs
502 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SINCOS
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
504 | INSTR_M4x4 omods dreg
',' sregs
507 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M4x4
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
509 | INSTR_M4x3 omods dreg
',' sregs
512 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M4x3
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
514 | INSTR_M3x4 omods dreg
',' sregs
517 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M3x4
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
519 | INSTR_M3x3 omods dreg
',' sregs
522 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M3x3
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
524 | INSTR_M3x2 omods dreg
',' sregs
527 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M3x2
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
529 | INSTR_DCL dclusage REG_OUTPUT
531 struct shader_reg reg
;
532 TRACE
("Output reg declaration\n");
533 ZeroMemory
(®
, sizeof
(reg
));
534 reg.type
= BWRITERSPR_OUTPUT
;
538 reg.writemask
= BWRITERSP_WRITEMASK_ALL
;
539 asm_ctx.funcs
->dcl_output
(&asm_ctx
, $2.dclusage
, $2.regnum
, ®
);
541 | INSTR_DCL dclusage REG_OUTPUT writemask
543 struct shader_reg reg
;
544 TRACE
("Output reg declaration\n");
545 ZeroMemory
(®
, sizeof
(reg
));
546 reg.type
= BWRITERSPR_OUTPUT
;
551 asm_ctx.funcs
->dcl_output
(&asm_ctx
, $2.dclusage
, $2.regnum
, ®
);
553 | INSTR_DCL dclusage omods dcl_inputreg
555 struct shader_reg reg
;
556 TRACE
("Input reg declaration\n");
558 asmparser_message
(&asm_ctx
, "Line %u: Shift modifier not allowed here\n",
560 set_parse_status
(&asm_ctx
, PARSE_ERR
);
562 if
(asm_ctx.shader
->version
== BWRITERPS_VERSION
(2, 0) ||
563 asm_ctx.shader
->version
== BWRITERPS_VERSION
(2, 1)) {
564 asmparser_message
(&asm_ctx
, "Line %u: Declaration not supported in PS 2\n",
566 set_parse_status
(&asm_ctx
, PARSE_ERR
);
568 ZeroMemory
(®
, sizeof
(reg
));
570 reg.regnum
= $4.regnum
;
573 reg.writemask
= BWRITERSP_WRITEMASK_ALL
;
574 asm_ctx.funcs
->dcl_input
(&asm_ctx
, $2.dclusage
, $2.regnum
, $3.mod
, ®
);
576 | INSTR_DCL dclusage omods dcl_inputreg writemask
578 struct shader_reg reg
;
579 TRACE
("Input reg declaration\n");
581 asmparser_message
(&asm_ctx
, "Line %u: Shift modifier not allowed here\n",
583 set_parse_status
(&asm_ctx
, PARSE_ERR
);
585 if
(asm_ctx.shader
->version
== BWRITERPS_VERSION
(2, 0) ||
586 asm_ctx.shader
->version
== BWRITERPS_VERSION
(2, 1)) {
587 asmparser_message
(&asm_ctx
, "Line %u: Declaration not supported in PS 2\n",
589 set_parse_status
(&asm_ctx
, PARSE_ERR
);
591 ZeroMemory
(®
, sizeof
(reg
));
593 reg.regnum
= $4.regnum
;
597 asm_ctx.funcs
->dcl_input
(&asm_ctx
, $2.dclusage
, $2.regnum
, $3.mod
, ®
);
599 | INSTR_DCL omods dcl_inputreg
601 struct shader_reg reg
;
602 TRACE
("Input reg declaration\n");
604 asmparser_message
(&asm_ctx
, "Line %u: Shift modifier not allowed here\n",
606 set_parse_status
(&asm_ctx
, PARSE_ERR
);
608 if
(asm_ctx.shader
->type
!= ST_PIXEL
) {
609 asmparser_message
(&asm_ctx
, "Line %u: Declaration needs a semantic\n",
611 set_parse_status
(&asm_ctx
, PARSE_ERR
);
613 ZeroMemory
(®
, sizeof
(reg
));
615 reg.regnum
= $3.regnum
;
618 reg.writemask
= BWRITERSP_WRITEMASK_ALL
;
619 asm_ctx.funcs
->dcl_input
(&asm_ctx
, 0, 0, $2.mod
, ®
);
621 | INSTR_DCL omods dcl_inputreg writemask
623 struct shader_reg reg
;
624 TRACE
("Input reg declaration\n");
626 asmparser_message
(&asm_ctx
, "Line %u: Shift modifier not allowed here\n",
628 set_parse_status
(&asm_ctx
, PARSE_ERR
);
630 if
(asm_ctx.shader
->type
!= ST_PIXEL
) {
631 asmparser_message
(&asm_ctx
, "Line %u: Declaration needs a semantic\n",
633 set_parse_status
(&asm_ctx
, PARSE_ERR
);
635 ZeroMemory
(®
, sizeof
(reg
));
637 reg.regnum
= $3.regnum
;
641 asm_ctx.funcs
->dcl_input
(&asm_ctx
, 0, 0, $2.mod
, ®
);
643 | INSTR_DCL sampdcl omods REG_SAMPLER
645 TRACE
("Sampler declared\n");
647 asmparser_message
(&asm_ctx
, "Line %u: Shift modifier not allowed here\n",
649 set_parse_status
(&asm_ctx
, PARSE_ERR
);
651 asm_ctx.funcs
->dcl_sampler
(&asm_ctx
, $2, $3.mod
, $4, asm_ctx.line_no
);
653 | INSTR_DCL omods REG_SAMPLER
655 TRACE
("Sampler declared\n");
657 asmparser_message
(&asm_ctx
, "Line %u: Shift modifier not allowed here\n",
659 set_parse_status
(&asm_ctx
, PARSE_ERR
);
661 if
(asm_ctx.shader
->type
!= ST_PIXEL
) {
662 asmparser_message
(&asm_ctx
, "Line %u: Declaration needs a sampler type\n",
664 set_parse_status
(&asm_ctx
, PARSE_ERR
);
666 asm_ctx.funcs
->dcl_sampler
(&asm_ctx
, BWRITERSTT_UNKNOWN
, $2.mod
, $3, asm_ctx.line_no
);
668 | INSTR_DCL sampdcl omods dcl_inputreg
670 TRACE
("Error rule: sampler decl of input reg\n");
671 asmparser_message
(&asm_ctx
, "Line %u: Sampler declarations of input regs is not valid\n",
673 set_parse_status
(&asm_ctx
, PARSE_WARN
);
675 | INSTR_DCL sampdcl omods REG_OUTPUT
677 TRACE
("Error rule: sampler decl of output reg\n");
678 asmparser_message
(&asm_ctx
, "Line %u: Sampler declarations of output regs is not valid\n",
680 set_parse_status
(&asm_ctx
, PARSE_WARN
);
682 | INSTR_DEF REG_CONSTFLOAT
',' IMMVAL
',' IMMVAL
',' IMMVAL
',' IMMVAL
684 asm_ctx.funcs
->constF
(&asm_ctx
, $2, $4.val
, $6.val
, $8.val
, $10.val
);
686 | INSTR_DEFI REG_CONSTINT
',' IMMVAL
',' IMMVAL
',' IMMVAL
',' IMMVAL
688 asm_ctx.funcs
->constI
(&asm_ctx
, $2, $4.val
, $6.val
, $8.val
, $10.val
);
690 | INSTR_DEFB REG_CONSTBOOL
',' IMMBOOL
692 asm_ctx.funcs
->constB
(&asm_ctx
, $2, $4);
697 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_REP
, 0, 0, 0, 0, &$2, 1);
702 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ENDREP
, 0, 0, 0, 0, 0, 0);
707 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_IF
, 0, 0, 0, 0, &$2, 1);
709 | INSTR_IF comp sregs
712 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_IFC
, 0, 0, $2, 0, &$3, 2);
717 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ELSE
, 0, 0, 0, 0, 0, 0);
722 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ENDIF
, 0, 0, 0, 0, 0, 0);
727 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_BREAK
, 0, 0, 0, 0, 0, 0);
729 | INSTR_BREAK comp sregs
732 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_BREAKC
, 0, 0, $2, 0, &$3, 2);
737 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_BREAKP
, 0, 0, 0, 0, &$2, 1);
742 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_CALL
, 0, 0, 0, 0, &$2, 1);
747 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_CALLNZ
, 0, 0, 0, 0, &$2, 2);
752 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LOOP
, 0, 0, 0, 0, &$2, 2);
757 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_RET
, 0, 0, 0, 0, 0, 0);
762 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ENDLOOP
, 0, 0, 0, 0, 0, 0);
767 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LABEL
, 0, 0, 0, 0, &$2, 1);
769 | INSTR_SETP comp dreg
',' sregs
772 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SETP
, 0, 0, $2, &$3, &$5, 2);
774 | INSTR_TEXLDL omods dreg
',' sregs
777 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_TEXLDL
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
779 | INSTR_LIT omods dreg
',' sregs
782 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LIT
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
784 | INSTR_MOVA omods dreg
',' sregs
787 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MOVA
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
789 | INSTR_CMP omods dreg
',' sregs
792 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_CMP
, $2.mod
, $2.shift
, 0, &$3, &$5, 3);
794 | INSTR_DP2ADD omods dreg
',' sregs
797 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_DP2ADD
, $2.mod
, $2.shift
, 0, &$3, &$5, 3);
802 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_TEXKILL
, 0, 0, 0, &$2, 0, 0);
804 | INSTR_TEXLD omods dreg
',' sregs
807 /* There is more than one acceptable syntax for texld:
808 with 1 sreg (PS 1.4) or
809 with 2 sregs (PS 2.0+)
810 Moreover, texld shares the same opcode as the tex instruction,
811 so there are a total of 3 valid syntaxes
812 These variations are handled in asmparser.c */
813 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_TEX
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
815 | INSTR_TEXLDP omods dreg
',' sregs
818 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_TEXLDP
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
820 | INSTR_TEXLDB omods dreg
',' sregs
823 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_TEXLDB
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
825 | INSTR_DSX omods dreg
',' sregs
828 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_DSX
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
830 | INSTR_DSY omods dreg
',' sregs
833 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_DSY
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
835 | INSTR_TEXLDD omods dreg
',' sregs
838 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_TEXLDD
, $2.mod
, $2.shift
, 0, &$3, &$5, 4);
841 dreg: dreg_name rel_reg
843 $$.regnum
= $1.regnum
;
845 $$.writemask
= BWRITERSP_WRITEMASK_ALL
;
846 $$.srcmod
= BWRITERSPSM_NONE
;
847 set_rel_reg
(&$$
, &$2);
849 | dreg_name writemask
851 $$.regnum
= $1.regnum
;
854 $$.srcmod
= BWRITERSPSM_NONE
;
860 $$.regnum
= $1; $$.type
= BWRITERSPR_TEMP
;
864 $$.regnum
= $1; $$.type
= BWRITERSPR_OUTPUT
;
868 $$.regnum
= $1; $$.type
= BWRITERSPR_INPUT
;
872 asmparser_message
(&asm_ctx
, "Line %u: Register c%u is not a valid destination register\n",
873 asm_ctx.line_no
, $1);
874 set_parse_status
(&asm_ctx
, PARSE_WARN
);
878 asmparser_message
(&asm_ctx
, "Line %u: Register i%u is not a valid destination register\n",
879 asm_ctx.line_no
, $1);
880 set_parse_status
(&asm_ctx
, PARSE_WARN
);
884 asmparser_message
(&asm_ctx
, "Line %u: Register b%u is not a valid destination register\n",
885 asm_ctx.line_no
, $1);
886 set_parse_status
(&asm_ctx
, PARSE_WARN
);
890 $$.regnum
= $1; $$.type
= BWRITERSPR_TEXTURE
;
894 $$.regnum
= $1; $$.type
= BWRITERSPR_TEXCRDOUT
;
898 asmparser_message
(&asm_ctx
, "Line %u: Register s%u is not a valid destination register\n",
899 asm_ctx.line_no
, $1);
900 set_parse_status
(&asm_ctx
, PARSE_WARN
);
904 $$.regnum
= BWRITERSRO_POSITION
; $$.type
= BWRITERSPR_RASTOUT
;
908 $$.regnum
= BWRITERSRO_POINT_SIZE
; $$.type
= BWRITERSPR_RASTOUT
;
912 $$.regnum
= BWRITERSRO_FOG
; $$.type
= BWRITERSPR_RASTOUT
;
916 $$.regnum
= $1; $$.type
= BWRITERSPR_ATTROUT
;
920 $$.regnum
= $1; $$.type
= BWRITERSPR_COLOROUT
;
924 $$.regnum
= 0; $$.type
= BWRITERSPR_DEPTHOUT
;
928 $$.regnum
= 0; $$.type
= BWRITERSPR_PREDICATE
;
932 asmparser_message
(&asm_ctx
, "Line %u: Register vPos is not a valid destination register\n",
934 set_parse_status
(&asm_ctx
, PARSE_WARN
);
938 asmparser_message
(&asm_ctx
, "Line %u: Register vFace is not a valid destination register\n",
940 set_parse_status
(&asm_ctx
, PARSE_WARN
);
944 /* index 0 is hardcoded for the addr register */
945 $$.regnum
= 0; $$.type
= BWRITERSPR_ADDR
;
949 asmparser_message
(&asm_ctx
, "Line %u: Register aL is not a valid destination register\n",
951 set_parse_status
(&asm_ctx
, PARSE_WARN
);
954 writemask: '.' wm_components
956 if
($2.writemask
== SWIZZLE_ERR
) {
957 asmparser_message
(&asm_ctx
, "Line %u: Invalid writemask specified\n",
959 set_parse_status
(&asm_ctx
, PARSE_ERR
);
960 /* Provide a correct writemask to prevent following complaints */
961 $$
= BWRITERSP_WRITEMASK_ALL
;
965 TRACE
("Writemask: %x\n", $$
);
969 wm_components: COMPONENT
971 $$.writemask
= 1 << $1;
975 | wm_components COMPONENT
977 if
($1.writemask
== SWIZZLE_ERR ||
$1.idx
== 4)
978 /* Wrong writemask */
979 $$.writemask
= SWIZZLE_ERR
;
982 $$.writemask
= SWIZZLE_ERR
;
984 $$.writemask
= $1.writemask |
(1 << $2);
992 $$
= BWRITERVS_NOSWIZZLE
;
993 TRACE
("Default swizzle: %08x\n", $$
);
997 if
($2.swizzle
== SWIZZLE_ERR
) {
998 asmparser_message
(&asm_ctx
, "Line %u: Invalid swizzle\n",
1000 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1001 /* Provide a correct swizzle to prevent following complaints */
1002 $$
= BWRITERVS_NOSWIZZLE
;
1007 $$
= $2.swizzle
<< BWRITERVS_SWIZZLE_SHIFT
;
1008 /* Fill the swizzle by extending the last component */
1009 last
= ($2.swizzle
>> 2 * ($2.idx
- 1)) & 0x03;
1010 for
(i
= $2.idx
; i
< 4; i
++){
1011 $$ |
= last
<< (BWRITERVS_SWIZZLE_SHIFT
+ 2 * i
);
1013 TRACE
("Got a swizzle: %08x\n", $$
);
1017 sw_components: COMPONENT
1022 | sw_components COMPONENT
1025 /* Too many sw_components */
1026 $$.swizzle
= SWIZZLE_ERR
;
1030 $$.swizzle
= $1.swizzle |
($2 << 2 * $1.idx
);
1031 $$.idx
= $1.idx
+ 1;
1042 $$.mod
= $1.mod |
$2.mod
;
1043 if
($1.shift
&& $2.shift
) {
1044 asmparser_message
(&asm_ctx
, "Line %u: More than one shift flag\n",
1046 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1047 $$.shift
= $1.shift
;
1049 $$.shift
= $1.shift |
$2.shift
;
1085 $$.mod
= BWRITERSPDM_SATURATE
;
1090 $$.mod
= BWRITERSPDM_PARTIALPRECISION
;
1095 $$.mod
= BWRITERSPDM_MSAMPCENTROID
;
1106 if
($$.count
== MAX_SRC_REGS
){
1107 asmparser_message
(&asm_ctx
, "Line %u: Too many source registers in this instruction\n",
1109 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1112 $$.reg
[$$.count
++] = $3;
1115 sreg: sreg_name rel_reg swizzle
1118 $$.regnum
= $1.regnum
;
1120 $$.srcmod
= BWRITERSPSM_NONE
;
1121 set_rel_reg
(&$$
, &$2);
1123 | sreg_name rel_reg smod swizzle
1126 $$.regnum
= $1.regnum
;
1127 set_rel_reg
(&$$
, &$2);
1131 |
'-' sreg_name rel_reg swizzle
1134 $$.regnum
= $2.regnum
;
1135 $$.srcmod
= BWRITERSPSM_NEG
;
1136 set_rel_reg
(&$$
, &$3);
1139 |
'-' sreg_name rel_reg smod swizzle
1142 $$.regnum
= $2.regnum
;
1143 set_rel_reg
(&$$
, &$3);
1145 case BWRITERSPSM_BIAS
: $$.srcmod
= BWRITERSPSM_BIASNEG
; break
;
1146 case BWRITERSPSM_X2
: $$.srcmod
= BWRITERSPSM_X2NEG
; break
;
1147 case BWRITERSPSM_SIGN
: $$.srcmod
= BWRITERSPSM_SIGNNEG
; break
;
1148 case BWRITERSPSM_ABS
: $$.srcmod
= BWRITERSPSM_ABSNEG
; break
;
1149 case BWRITERSPSM_DZ
:
1150 asmparser_message
(&asm_ctx
, "Line %u: Incompatible source modifiers: NEG and DZ\n",
1152 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1154 case BWRITERSPSM_DW
:
1155 asmparser_message
(&asm_ctx
, "Line %u: Incompatible source modifiers: NEG and DW\n",
1157 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1160 FIXME
("Unhandled combination of NEGATE and %u\n", $4);
1164 | IMMVAL
'-' sreg_name rel_reg swizzle
1166 if
($1.val
!= 1.0 ||
(!$1.integer
)) {
1167 asmparser_message
(&asm_ctx
, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP, "
1168 "%g - reg found\n", asm_ctx.line_no
, $1.val
);
1169 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1171 /* Complement - not compatible with other source modifiers */
1173 $$.regnum
= $3.regnum
;
1174 $$.srcmod
= BWRITERSPSM_COMP
;
1175 set_rel_reg
(&$$
, &$4);
1178 | IMMVAL
'-' sreg_name rel_reg smod swizzle
1180 /* For nicer error reporting */
1181 if
($1.val
!= 1.0 ||
(!$1.integer
)) {
1182 asmparser_message
(&asm_ctx
, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP\n",
1184 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1186 asmparser_message
(&asm_ctx
, "Line %u: Incompatible source modifiers: D3DSPSM_COMP and %s\n",
1188 debug_print_srcmod
($5));
1189 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1192 | SMOD_NOT sreg_name swizzle
1195 $$.regnum
= $2.regnum
;
1197 $$.srcmod
= BWRITERSPSM_NOT
;
1201 rel_reg: /* empty */
1203 $$.has_rel_reg
= FALSE
;
1204 $$.additional_offset
= 0;
1208 $$.has_rel_reg
= FALSE
;
1209 $$.additional_offset
= $2.val
;
1211 |
'[' relreg_name swizzle
']'
1213 $$.has_rel_reg
= TRUE
;
1215 $$.additional_offset
= 0;
1216 $$.rel_regnum
= $2.regnum
;
1219 |
'[' immsum
'+' relreg_name swizzle
']'
1221 $$.has_rel_reg
= TRUE
;
1223 $$.additional_offset
= $2.val
;
1224 $$.rel_regnum
= $4.regnum
;
1227 |
'[' relreg_name swizzle
'+' immsum
']'
1229 $$.has_rel_reg
= TRUE
;
1231 $$.additional_offset
= $5.val
;
1232 $$.rel_regnum
= $2.regnum
;
1235 |
'[' immsum
'+' relreg_name swizzle
'+' immsum
']'
1237 $$.has_rel_reg
= TRUE
;
1239 $$.additional_offset
= $2.val
+ $7.val
;
1240 $$.rel_regnum
= $4.regnum
;
1247 asmparser_message
(&asm_ctx
, "Line %u: Unexpected float %f\n",
1248 asm_ctx.line_no
, $1.val
);
1249 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1256 asmparser_message
(&asm_ctx
, "Line %u: Unexpected float %f\n",
1257 asm_ctx.line_no
, $3.val
);
1258 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1260 $$.val
= $1.val
+ $3.val
;
1265 $$
= BWRITERSPSM_BIAS
;
1269 $$
= BWRITERSPSM_X2
;
1273 $$
= BWRITERSPSM_SIGN
;
1277 $$
= BWRITERSPSM_DZ
;
1281 $$
= BWRITERSPSM_DW
;
1285 $$
= BWRITERSPSM_ABS
;
1288 relreg_name: REG_ADDRESS
1290 $$.regnum
= 0; $$.type
= BWRITERSPR_ADDR
;
1294 $$.regnum
= 0; $$.type
= BWRITERSPR_LOOP
;
1299 $$.regnum
= $1; $$.type
= BWRITERSPR_TEMP
;
1303 asmparser_message
(&asm_ctx
, "Line %u: Register o%u is not a valid source register\n",
1304 asm_ctx.line_no
, $1);
1305 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1309 $$.regnum
= $1; $$.type
= BWRITERSPR_INPUT
;
1313 $$.regnum
= $1; $$.type
= BWRITERSPR_CONST
;
1317 $$.regnum
= $1; $$.type
= BWRITERSPR_CONSTINT
;
1321 $$.regnum
= $1; $$.type
= BWRITERSPR_CONSTBOOL
;
1325 $$.regnum
= $1; $$.type
= BWRITERSPR_TEXTURE
;
1329 asmparser_message
(&asm_ctx
, "Line %u: Register oT%u is not a valid source register\n",
1330 asm_ctx.line_no
, $1);
1331 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1335 $$.regnum
= $1; $$.type
= BWRITERSPR_SAMPLER
;
1339 asmparser_message
(&asm_ctx
, "Line %u: Register oPos is not a valid source register\n",
1341 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1345 asmparser_message
(&asm_ctx
, "Line %u: Register oFog is not a valid source register\n",
1347 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1351 asmparser_message
(&asm_ctx
, "Line %u: Register oD%u is not a valid source register\n",
1352 asm_ctx.line_no
, $1);
1353 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1357 asmparser_message
(&asm_ctx
, "Line %u: Register oC%u is not a valid source register\n",
1358 asm_ctx.line_no
, $1);
1359 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1363 asmparser_message
(&asm_ctx
, "Line %u: Register oDepth is not a valid source register\n",
1365 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1369 $$.regnum
= 0; $$.type
= BWRITERSPR_PREDICATE
;
1373 $$.regnum
= 0; $$.type
= BWRITERSPR_MISCTYPE
;
1377 $$.regnum
= 1; $$.type
= BWRITERSPR_MISCTYPE
;
1381 $$.regnum
= 0; $$.type
= BWRITERSPR_ADDR
;
1385 $$.regnum
= 0; $$.type
= BWRITERSPR_LOOP
;
1389 $$.regnum
= $1; $$.type
= BWRITERSPR_LABEL
;
1392 comp: COMP_GT
{ $$
= BWRITER_COMPARISON_GT
; }
1393 | COMP_LT
{ $$
= BWRITER_COMPARISON_LT
; }
1394 | COMP_GE
{ $$
= BWRITER_COMPARISON_GE
; }
1395 | COMP_LE
{ $$
= BWRITER_COMPARISON_LE
; }
1396 | COMP_EQ
{ $$
= BWRITER_COMPARISON_EQ
; }
1397 | COMP_NE
{ $$
= BWRITER_COMPARISON_NE
; }
1399 dclusage: USAGE_POSITION
1401 TRACE
("dcl_position%u\n", $1);
1403 $$.dclusage
= BWRITERDECLUSAGE_POSITION
;
1407 TRACE
("dcl_blendweight%u\n", $1);
1409 $$.dclusage
= BWRITERDECLUSAGE_BLENDWEIGHT
;
1411 | USAGE_BLENDINDICES
1413 TRACE
("dcl_blendindices%u\n", $1);
1415 $$.dclusage
= BWRITERDECLUSAGE_BLENDINDICES
;
1419 TRACE
("dcl_normal%u\n", $1);
1421 $$.dclusage
= BWRITERDECLUSAGE_NORMAL
;
1425 TRACE
("dcl_psize%u\n", $1);
1427 $$.dclusage
= BWRITERDECLUSAGE_PSIZE
;
1431 TRACE
("dcl_texcoord%u\n", $1);
1433 $$.dclusage
= BWRITERDECLUSAGE_TEXCOORD
;
1437 TRACE
("dcl_tangent%u\n", $1);
1439 $$.dclusage
= BWRITERDECLUSAGE_TANGENT
;
1443 TRACE
("dcl_binormal%u\n", $1);
1445 $$.dclusage
= BWRITERDECLUSAGE_BINORMAL
;
1449 TRACE
("dcl_tessfactor%u\n", $1);
1451 $$.dclusage
= BWRITERDECLUSAGE_TESSFACTOR
;
1455 TRACE
("dcl_positiont%u\n", $1);
1457 $$.dclusage
= BWRITERDECLUSAGE_POSITIONT
;
1461 TRACE
("dcl_color%u\n", $1);
1463 $$.dclusage
= BWRITERDECLUSAGE_COLOR
;
1467 TRACE
("dcl_fog%u\n", $1);
1469 $$.dclusage
= BWRITERDECLUSAGE_FOG
;
1473 TRACE
("dcl_depth%u\n", $1);
1475 $$.dclusage
= BWRITERDECLUSAGE_DEPTH
;
1479 TRACE
("dcl_sample%u\n", $1);
1481 $$.dclusage
= BWRITERDECLUSAGE_SAMPLE
;
1484 dcl_inputreg: REG_INPUT
1486 $$.regnum
= $1; $$.type
= BWRITERSPR_INPUT
;
1490 $$.regnum
= $1; $$.type
= BWRITERSPR_TEXTURE
;
1493 sampdcl: SAMPTYPE_1D
1503 $$
= BWRITERSTT_CUBE
;
1507 $$
= BWRITERSTT_VOLUME
;
1510 predicate: '(' REG_PREDICATE swizzle
')'
1512 $$.type
= BWRITERSPR_PREDICATE
;
1515 $$.srcmod
= BWRITERSPSM_NONE
;
1518 |
'(' SMOD_NOT REG_PREDICATE swizzle
')'
1520 $$.type
= BWRITERSPR_PREDICATE
;
1523 $$.srcmod
= BWRITERSPSM_NOT
;
1529 void asmshader_error
(char const *s
) {
1530 asmparser_message
(&asm_ctx
, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no
, s
);
1531 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1534 /* Error reporting function */
1535 void asmparser_message
(struct asm_parser
*ctx
, const char *fmt
, ...
) {
1540 if
(ctx
->messagecapacity
== 0) {
1541 ctx
->messages
= asm_alloc
(MESSAGEBUFFER_INITIAL_SIZE
);
1542 if
(ctx
->messages
== NULL
) {
1543 ERR
("Error allocating memory for parser messages\n");
1546 ctx
->messagecapacity
= MESSAGEBUFFER_INITIAL_SIZE
;
1550 va_start
(args
, fmt
);
1551 rc
= vsnprintf
(ctx
->messages
+ ctx
->messagesize
,
1552 ctx
->messagecapacity
- ctx
->messagesize
, fmt
, args
);
1555 if
(rc
< 0 ||
/* C89 */
1556 rc
>= ctx
->messagecapacity
- ctx
->messagesize
) { /* C99 */
1557 /* Resize the buffer */
1558 newsize
= ctx
->messagecapacity
* 2;
1559 newbuffer
= asm_realloc
(ctx
->messages
, newsize
);
1560 if
(newbuffer
== NULL
){
1561 ERR
("Error reallocating memory for parser messages\n");
1564 ctx
->messages
= newbuffer
;
1565 ctx
->messagecapacity
= newsize
;
1567 ctx
->messagesize
+= rc
;
1573 /* New status is the worst between current status and parameter value */
1574 void set_parse_status
(struct asm_parser
*ctx
, enum parse_status status
) {
1575 if
(status
== PARSE_ERR
) ctx
->status
= PARSE_ERR
;
1576 else if
(status
== PARSE_WARN
&& ctx
->status
== PARSE_SUCCESS
) ctx
->status
= PARSE_WARN
;
1579 struct bwriter_shader
*parse_asm_shader
(char **messages
) {
1580 struct bwriter_shader
*ret
= NULL
;
1582 asm_ctx.shader
= NULL
;
1583 asm_ctx.status
= PARSE_SUCCESS
;
1584 asm_ctx.messagesize
= asm_ctx.messagecapacity
= 0;
1585 asm_ctx.line_no
= 1;
1589 if
(asm_ctx.status
!= PARSE_ERR
) ret
= asm_ctx.shader
;
1590 else if
(asm_ctx.shader
) SlDeleteShader
(asm_ctx.shader
);
1593 if
(asm_ctx.messagesize
) {
1594 /* Shrink the buffer to the used size */
1595 *messages
= asm_realloc
(asm_ctx.messages
, asm_ctx.messagesize
+ 1);
1597 ERR
("Out of memory, no messages reported\n");
1598 asm_free
(asm_ctx.messages
);
1604 if
(asm_ctx.messagecapacity
) asm_free
(asm_ctx.messages
);