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
;
64 struct shader_reg reg
;
82 BWRITER_COMPARISON_TYPE comptype
;
87 BWRITERSAMPLER_TEXTURE_TYPE samplertype
;
88 struct rel_reg rel_reg
;
89 struct src_regs sregs
;
92 /* Common instructions between vertex and pixel shaders */
142 /* Vertex shader only instructions */
147 %token
<regnum
> REG_TEMP
148 %token
<regnum
> REG_OUTPUT
149 %token
<regnum
> REG_INPUT
150 %token
<regnum
> REG_CONSTFLOAT
151 %token
<regnum
> REG_CONSTINT
152 %token
<regnum
> REG_CONSTBOOL
153 %token
<regnum
> REG_TEXTURE
154 %token
<regnum
> REG_SAMPLER
155 %token
<regnum
> REG_TEXCRDOUT
159 %token
<regnum
> REG_VERTEXCOLOR
160 %token
<regnum
> REG_FRAGCOLOR
167 %token
<regnum
> REG_LABEL
185 /* Output modifiers */
198 /* Source register modifiers */
206 %token SAMPTYPE_VOLUME
208 /* Usage declaration tokens */
209 %token
<regnum
> USAGE_POSITION
210 %token
<regnum
> USAGE_BLENDWEIGHT
211 %token
<regnum
> USAGE_BLENDINDICES
212 %token
<regnum
> USAGE_NORMAL
213 %token
<regnum
> USAGE_PSIZE
214 %token
<regnum
> USAGE_TEXCOORD
215 %token
<regnum
> USAGE_TANGENT
216 %token
<regnum
> USAGE_BINORMAL
217 %token
<regnum
> USAGE_TESSFACTOR
218 %token
<regnum
> USAGE_POSITIONT
219 %token
<regnum
> USAGE_COLOR
220 %token
<regnum
> USAGE_FOG
221 %token
<regnum
> USAGE_DEPTH
222 %token
<regnum
> USAGE_SAMPLE
225 %token
<component
> COMPONENT
226 %token
<immval
> IMMVAL
228 %type
<reg
> dreg_name
230 %type
<reg
> sreg_name
231 %type
<reg
> relreg_name
234 %type
<writemask
> writemask
235 %type
<wm_components
> wm_components
236 %type
<swizzle
> swizzle
237 %type
<sw_components
> sw_components
238 %type
<modshift
> omods
239 %type
<modshift
> omodifier
240 %type
<comptype
> comp
241 %type
<declaration
> dclusage
242 %type
<samplertype
> sampdcl
243 %type
<rel_reg
> rel_reg
244 %type
<reg
> predicate
245 %type
<immval
> immsum
250 shader: version_marker instructions
252 asm_ctx.funcs
->end
(&asm_ctx
);
255 version_marker: VER_VS10
257 TRACE
("Vertex shader 1.0\n");
258 set_parse_status
(&asm_ctx
, PARSE_ERR
);
263 TRACE
("Vertex shader 1.1\n");
264 set_parse_status
(&asm_ctx
, PARSE_ERR
);
269 TRACE
("Vertex shader 2.0\n");
270 set_parse_status
(&asm_ctx
, PARSE_ERR
);
275 TRACE
("Vertex shader 2.x\n");
276 set_parse_status
(&asm_ctx
, PARSE_ERR
);
281 TRACE
("Vertex shader 3.0\n");
282 create_vs30_parser
(&asm_ctx
);
286 TRACE
("Pixel shader 1.0\n");
287 set_parse_status
(&asm_ctx
, PARSE_ERR
);
292 TRACE
("Pixel shader 1.1\n");
293 set_parse_status
(&asm_ctx
, PARSE_ERR
);
298 TRACE
("Pixel shader 1.2\n");
299 set_parse_status
(&asm_ctx
, PARSE_ERR
);
304 TRACE
("Pixel shader 1.3\n");
305 set_parse_status
(&asm_ctx
, PARSE_ERR
);
310 TRACE
("Pixel shader 1.4\n");
311 set_parse_status
(&asm_ctx
, PARSE_ERR
);
316 TRACE
("Pixel shader 2.0\n");
317 set_parse_status
(&asm_ctx
, PARSE_ERR
);
322 TRACE
("Pixel shader 2.x\n");
323 set_parse_status
(&asm_ctx
, PARSE_ERR
);
328 TRACE
("Pixel shader 3.0\n");
329 set_parse_status
(&asm_ctx
, PARSE_ERR
);
333 instructions: /* empty */
334 | instructions complexinstr
339 complexinstr: instruction
343 | predicate instruction
345 TRACE
("predicate\n");
346 asm_ctx.funcs
->predicate
(&asm_ctx
, &$1);
349 instruction: INSTR_ADD omods dreg
',' sregs
352 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ADD
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
357 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_NOP
, 0, 0, 0, 0, 0, 0);
359 | INSTR_MOV omods dreg
',' sregs
362 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MOV
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
364 | INSTR_SUB omods dreg
',' sregs
367 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SUB
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
369 | INSTR_MAD omods dreg
',' sregs
372 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MAD
, $2.mod
, $2.shift
, 0, &$3, &$5, 3);
374 | INSTR_MUL omods dreg
',' sregs
377 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MUL
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
379 | INSTR_RCP omods dreg
',' sregs
382 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_RCP
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
384 | INSTR_RSQ omods dreg
',' sregs
387 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_RSQ
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
389 | INSTR_DP3 omods dreg
',' sregs
392 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_DP3
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
394 | INSTR_DP4 omods dreg
',' sregs
397 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_DP4
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
399 | INSTR_MIN omods dreg
',' sregs
402 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MIN
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
404 | INSTR_MAX omods dreg
',' sregs
407 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MAX
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
409 | INSTR_SLT omods dreg
',' sregs
412 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SLT
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
414 | INSTR_SGE omods dreg
',' sregs
417 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SGE
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
419 | INSTR_ABS omods dreg
',' sregs
422 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ABS
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
424 | INSTR_EXP omods dreg
',' sregs
427 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_EXP
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
429 | INSTR_LOG omods dreg
',' sregs
432 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LOG
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
434 | INSTR_LOGP omods dreg
',' sregs
437 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LOGP
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
439 | INSTR_EXPP omods dreg
',' sregs
442 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_EXPP
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
444 | INSTR_DST omods dreg
',' sregs
447 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_DST
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
449 | INSTR_LRP omods dreg
',' sregs
452 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LRP
, $2.mod
, $2.shift
, 0, &$3, &$5, 3);
454 | INSTR_FRC omods dreg
',' sregs
457 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_FRC
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
459 | INSTR_POW omods dreg
',' sregs
462 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_POW
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
464 | INSTR_CRS omods dreg
',' sregs
467 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_CRS
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
469 | INSTR_SGN omods dreg
',' sregs
472 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SGN
, $2.mod
, $2.shift
, 0, &$3, &$5, 3);
474 | INSTR_NRM omods dreg
',' sregs
477 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_NRM
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
479 | INSTR_SINCOS omods dreg
',' sregs
482 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SINCOS
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
484 | INSTR_M4x4 omods dreg
',' sregs
487 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M4x4
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
489 | INSTR_M4x3 omods dreg
',' sregs
492 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M4x3
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
494 | INSTR_M3x4 omods dreg
',' sregs
497 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M3x4
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
499 | INSTR_M3x3 omods dreg
',' sregs
502 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M3x3
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
504 | INSTR_M3x2 omods dreg
',' sregs
507 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_M3x2
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
509 | INSTR_DCL dclusage REG_OUTPUT
511 struct shader_reg reg
;
512 TRACE
("Output reg declaration\n");
513 ZeroMemory
(®
, sizeof
(reg
));
514 reg.type
= BWRITERSPR_OUTPUT
;
518 reg.writemask
= BWRITERSP_WRITEMASK_ALL
;
519 asm_ctx.funcs
->dcl_output
(&asm_ctx
, $2.dclusage
, $2.regnum
, ®
);
521 | INSTR_DCL dclusage REG_OUTPUT writemask
523 struct shader_reg reg
;
524 TRACE
("Output reg declaration\n");
525 ZeroMemory
(®
, sizeof
(reg
));
526 reg.type
= BWRITERSPR_OUTPUT
;
531 asm_ctx.funcs
->dcl_output
(&asm_ctx
, $2.dclusage
, $2.regnum
, ®
);
533 | INSTR_DCL dclusage REG_INPUT
535 struct shader_reg reg
;
536 TRACE
("Input reg declaration\n");
537 ZeroMemory
(®
, sizeof
(reg
));
538 reg.type
= BWRITERSPR_INPUT
;
542 reg.writemask
= BWRITERSP_WRITEMASK_ALL
;
543 asm_ctx.funcs
->dcl_input
(&asm_ctx
, $2.dclusage
, $2.regnum
, ®
);
545 | INSTR_DCL dclusage REG_INPUT writemask
547 struct shader_reg reg
;
548 TRACE
("Input reg declaration\n");
549 ZeroMemory
(®
, sizeof
(reg
));
550 reg.type
= BWRITERSPR_INPUT
;
555 asm_ctx.funcs
->dcl_input
(&asm_ctx
, $2.dclusage
, $2.regnum
, ®
);
557 | INSTR_DCL sampdcl REG_SAMPLER
559 TRACE
("Sampler declared\n");
560 asm_ctx.funcs
->dcl_sampler
(&asm_ctx
, $2, $3, asm_ctx.line_no
);
562 | INSTR_DCL sampdcl REG_INPUT
564 TRACE
("Error rule: sampler decl of input reg\n");
565 asmparser_message
(&asm_ctx
, "Line %u: Sampler declarations of input regs is not valid\n",
567 set_parse_status
(&asm_ctx
, PARSE_WARN
);
569 | INSTR_DCL sampdcl REG_OUTPUT
571 TRACE
("Error rule: sampler decl of output reg\n");
572 asmparser_message
(&asm_ctx
, "Line %u: Sampler declarations of output regs is not valid\n",
574 set_parse_status
(&asm_ctx
, PARSE_WARN
);
579 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_REP
, 0, 0, 0, 0, &$2, 1);
584 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ENDREP
, 0, 0, 0, 0, 0, 0);
589 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_IF
, 0, 0, 0, 0, &$2, 1);
591 | INSTR_IF comp sregs
594 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_IFC
, 0, 0, $2, 0, &$3, 2);
599 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ELSE
, 0, 0, 0, 0, 0, 0);
604 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ENDIF
, 0, 0, 0, 0, 0, 0);
609 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_BREAK
, 0, 0, 0, 0, 0, 0);
611 | INSTR_BREAK comp sregs
614 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_BREAKC
, 0, 0, $2, 0, &$3, 2);
619 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_BREAKP
, 0, 0, 0, 0, &$2, 1);
624 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_CALL
, 0, 0, 0, 0, &$2, 1);
629 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_CALLNZ
, 0, 0, 0, 0, &$2, 2);
634 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LOOP
, 0, 0, 0, 0, &$2, 2);
639 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_RET
, 0, 0, 0, 0, 0, 0);
644 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_ENDLOOP
, 0, 0, 0, 0, 0, 0);
649 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LABEL
, 0, 0, 0, 0, &$2, 1);
651 | INSTR_SETP comp dreg
',' sregs
654 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_SETP
, 0, 0, $2, &$3, &$5, 2);
656 | INSTR_TEXLDL omods dreg
',' sregs
659 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_TEXLDL
, $2.mod
, $2.shift
, 0, &$3, &$5, 2);
661 | INSTR_LIT omods dreg
',' sregs
664 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_LIT
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
666 | INSTR_MOVA omods dreg
',' sregs
669 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MOVA
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
672 dreg: dreg_name rel_reg
674 $$.regnum
= $1.regnum
;
676 $$.writemask
= BWRITERSP_WRITEMASK_ALL
;
677 $$.srcmod
= BWRITERSPSM_NONE
;
678 set_rel_reg
(&$$
, &$2);
680 | dreg_name writemask
682 $$.regnum
= $1.regnum
;
685 $$.srcmod
= BWRITERSPSM_NONE
;
691 $$.regnum
= $1; $$.type
= BWRITERSPR_TEMP
;
695 $$.regnum
= $1; $$.type
= BWRITERSPR_OUTPUT
;
699 asmparser_message
(&asm_ctx
, "Line %u: Register v%u is not a valid destination register\n",
700 asm_ctx.line_no
, $1);
701 set_parse_status
(&asm_ctx
, PARSE_WARN
);
705 asmparser_message
(&asm_ctx
, "Line %u: Register c%u is not a valid destination register\n",
706 asm_ctx.line_no
, $1);
707 set_parse_status
(&asm_ctx
, PARSE_WARN
);
711 asmparser_message
(&asm_ctx
, "Line %u: Register i%u is not a valid destination register\n",
712 asm_ctx.line_no
, $1);
713 set_parse_status
(&asm_ctx
, PARSE_WARN
);
717 asmparser_message
(&asm_ctx
, "Line %u: Register b%u is not a valid destination register\n",
718 asm_ctx.line_no
, $1);
719 set_parse_status
(&asm_ctx
, PARSE_WARN
);
723 $$.regnum
= $1; $$.type
= BWRITERSPR_TEXTURE
;
727 $$.regnum
= $1; $$.type
= BWRITERSPR_TEXCRDOUT
;
731 asmparser_message
(&asm_ctx
, "Line %u: Register s%u is not a valid destination register\n",
732 asm_ctx.line_no
, $1);
733 set_parse_status
(&asm_ctx
, PARSE_WARN
);
737 $$.regnum
= BWRITERSRO_POSITION
; $$.type
= BWRITERSPR_RASTOUT
;
741 $$.regnum
= BWRITERSRO_POINT_SIZE
; $$.type
= BWRITERSPR_RASTOUT
;
745 $$.regnum
= BWRITERSRO_FOG
; $$.type
= BWRITERSPR_RASTOUT
;
749 $$.regnum
= $1; $$.type
= BWRITERSPR_ATTROUT
;
753 $$.regnum
= $1; $$.type
= BWRITERSPR_COLOROUT
;
757 $$.regnum
= 0; $$.type
= BWRITERSPR_DEPTHOUT
;
761 $$.regnum
= 0; $$.type
= BWRITERSPR_PREDICATE
;
765 asmparser_message
(&asm_ctx
, "Line %u: Register vPos is not a valid destination register\n",
767 set_parse_status
(&asm_ctx
, PARSE_WARN
);
771 asmparser_message
(&asm_ctx
, "Line %u: Register vFace is not a valid destination register\n",
773 set_parse_status
(&asm_ctx
, PARSE_WARN
);
777 /* index 0 is hardcoded for the addr register */
778 $$.regnum
= 0; $$.type
= BWRITERSPR_ADDR
;
782 asmparser_message
(&asm_ctx
, "Line %u: Register aL is not a valid destination register\n",
784 set_parse_status
(&asm_ctx
, PARSE_WARN
);
787 writemask: '.' wm_components
789 if
($2.writemask
== SWIZZLE_ERR
) {
790 asmparser_message
(&asm_ctx
, "Line %u: Invalid writemask specified\n",
792 set_parse_status
(&asm_ctx
, PARSE_ERR
);
793 /* Provide a correct writemask to prevent following complaints */
794 $$
= BWRITERSP_WRITEMASK_ALL
;
798 TRACE
("Writemask: %x\n", $$
);
802 wm_components: COMPONENT
804 $$.writemask
= 1 << $1;
808 | wm_components COMPONENT
810 if
($1.writemask
== SWIZZLE_ERR ||
$1.idx
== 4)
811 /* Wrong writemask */
812 $$.writemask
= SWIZZLE_ERR
;
815 $$.writemask
= SWIZZLE_ERR
;
817 $$.writemask
= $1.writemask |
(1 << $2);
825 $$
= BWRITERVS_NOSWIZZLE
;
826 TRACE
("Default swizzle: %08x\n", $$
);
830 if
($2.swizzle
== SWIZZLE_ERR
) {
831 asmparser_message
(&asm_ctx
, "Line %u: Invalid swizzle\n",
833 set_parse_status
(&asm_ctx
, PARSE_ERR
);
834 /* Provide a correct swizzle to prevent following complaints */
835 $$
= BWRITERVS_NOSWIZZLE
;
840 $$
= $2.swizzle
<< BWRITERVS_SWIZZLE_SHIFT
;
841 /* Fill the swizzle by extending the last component */
842 last
= ($2.swizzle
>> 2 * ($2.idx
- 1)) & 0x03;
843 for
(i
= $2.idx
; i
< 4; i
++){
844 $$ |
= last
<< (BWRITERVS_SWIZZLE_SHIFT
+ 2 * i
);
846 TRACE
("Got a swizzle: %08x\n", $$
);
850 sw_components: COMPONENT
855 | sw_components COMPONENT
858 /* Too many sw_components */
859 $$.swizzle
= SWIZZLE_ERR
;
863 $$.swizzle
= $1.swizzle |
($2 << 2 * $1.idx
);
875 $$.mod
= $1.mod |
$2.mod
;
876 if
($1.shift
&& $2.shift
) {
877 asmparser_message
(&asm_ctx
, "Line %u: More than one shift flag\n",
879 set_parse_status
(&asm_ctx
, PARSE_ERR
);
882 $$.shift
= $1.shift |
$2.shift
;
888 $$.mod
= BWRITERSPDM_SATURATE
;
893 $$.mod
= BWRITERSPDM_PARTIALPRECISION
;
898 $$.mod
= BWRITERSPDM_MSAMPCENTROID
;
909 if
($$.count
== MAX_SRC_REGS
){
910 asmparser_message
(&asm_ctx
, "Line %u: Too many source registers in this instruction\n",
912 set_parse_status
(&asm_ctx
, PARSE_ERR
);
915 $$.reg
[$$.count
++] = $3;
918 sreg: sreg_name rel_reg swizzle
921 $$.regnum
= $1.regnum
;
923 $$.srcmod
= BWRITERSPSM_NONE
;
924 set_rel_reg
(&$$
, &$2);
926 | sreg_name rel_reg smod swizzle
929 $$.regnum
= $1.regnum
;
930 set_rel_reg
(&$$
, &$2);
934 |
'-' sreg_name rel_reg swizzle
937 $$.regnum
= $2.regnum
;
938 $$.srcmod
= BWRITERSPSM_NEG
;
939 set_rel_reg
(&$$
, &$3);
942 |
'-' sreg_name rel_reg smod swizzle
945 $$.regnum
= $2.regnum
;
946 set_rel_reg
(&$$
, &$3);
948 case BWRITERSPSM_ABS
: $$.srcmod
= BWRITERSPSM_ABSNEG
; break
;
950 FIXME
("Unhandled combination of NEGATE and %u\n", $4);
954 | SMOD_NOT sreg_name swizzle
957 $$.regnum
= $2.regnum
;
959 $$.srcmod
= BWRITERSPSM_NOT
;
965 $$.has_rel_reg
= FALSE
;
966 $$.additional_offset
= 0;
970 $$.has_rel_reg
= FALSE
;
971 $$.additional_offset
= $2.val
;
973 |
'[' relreg_name swizzle
']'
975 $$.has_rel_reg
= TRUE
;
977 $$.additional_offset
= 0;
978 $$.rel_regnum
= $2.regnum
;
981 |
'[' immsum
'+' relreg_name swizzle
']'
983 $$.has_rel_reg
= TRUE
;
985 $$.additional_offset
= $2.val
;
986 $$.rel_regnum
= $4.regnum
;
989 |
'[' relreg_name swizzle
'+' immsum
']'
991 $$.has_rel_reg
= TRUE
;
993 $$.additional_offset
= $5.val
;
994 $$.rel_regnum
= $2.regnum
;
997 |
'[' immsum
'+' relreg_name swizzle
'+' immsum
']'
999 $$.has_rel_reg
= TRUE
;
1001 $$.additional_offset
= $2.val
+ $7.val
;
1002 $$.rel_regnum
= $4.regnum
;
1009 asmparser_message
(&asm_ctx
, "Line %u: Unexpected float %f\n",
1010 asm_ctx.line_no
, $1.val
);
1011 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1018 asmparser_message
(&asm_ctx
, "Line %u: Unexpected float %f\n",
1019 asm_ctx.line_no
, $3.val
);
1020 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1022 $$.val
= $1.val
+ $3.val
;
1027 $$
= BWRITERSPSM_ABS
;
1030 relreg_name: REG_ADDRESS
1032 $$.regnum
= 0; $$.type
= BWRITERSPR_ADDR
;
1036 $$.regnum
= 0; $$.type
= BWRITERSPR_LOOP
;
1041 $$.regnum
= $1; $$.type
= BWRITERSPR_TEMP
;
1045 asmparser_message
(&asm_ctx
, "Line %u: Register o%u is not a valid source register\n",
1046 asm_ctx.line_no
, $1);
1047 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1051 $$.regnum
= $1; $$.type
= BWRITERSPR_INPUT
;
1055 $$.regnum
= $1; $$.type
= BWRITERSPR_CONST
;
1059 $$.regnum
= $1; $$.type
= BWRITERSPR_CONSTINT
;
1063 $$.regnum
= $1; $$.type
= BWRITERSPR_CONSTBOOL
;
1067 $$.regnum
= $1; $$.type
= BWRITERSPR_TEXTURE
;
1071 asmparser_message
(&asm_ctx
, "Line %u: Register oT%u is not a valid source register\n",
1072 asm_ctx.line_no
, $1);
1073 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1077 $$.regnum
= $1; $$.type
= BWRITERSPR_SAMPLER
;
1081 asmparser_message
(&asm_ctx
, "Line %u: Register oPos is not a valid source register\n",
1083 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1087 asmparser_message
(&asm_ctx
, "Line %u: Register oFog is not a valid source register\n",
1089 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1093 asmparser_message
(&asm_ctx
, "Line %u: Register oD%u is not a valid source register\n",
1094 asm_ctx.line_no
, $1);
1095 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1099 asmparser_message
(&asm_ctx
, "Line %u: Register oC%u is not a valid source register\n",
1100 asm_ctx.line_no
, $1);
1101 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1105 asmparser_message
(&asm_ctx
, "Line %u: Register oDepth is not a valid source register\n",
1107 set_parse_status
(&asm_ctx
, PARSE_WARN
);
1111 $$.regnum
= 0; $$.type
= BWRITERSPR_PREDICATE
;
1115 $$.regnum
= 0; $$.type
= BWRITERSPR_MISCTYPE
;
1119 $$.regnum
= 1; $$.type
= BWRITERSPR_MISCTYPE
;
1123 $$.regnum
= 0; $$.type
= BWRITERSPR_ADDR
;
1127 $$.regnum
= 0; $$.type
= BWRITERSPR_LOOP
;
1131 $$.regnum
= $1; $$.type
= BWRITERSPR_LABEL
;
1134 comp: COMP_GT
{ $$
= BWRITER_COMPARISON_GT
; }
1135 | COMP_LT
{ $$
= BWRITER_COMPARISON_LT
; }
1136 | COMP_GE
{ $$
= BWRITER_COMPARISON_GE
; }
1137 | COMP_LE
{ $$
= BWRITER_COMPARISON_LE
; }
1138 | COMP_EQ
{ $$
= BWRITER_COMPARISON_EQ
; }
1139 | COMP_NE
{ $$
= BWRITER_COMPARISON_NE
; }
1141 dclusage: USAGE_POSITION
1143 TRACE
("dcl_position%u\n", $1);
1145 $$.dclusage
= BWRITERDECLUSAGE_POSITION
;
1149 TRACE
("dcl_blendweight%u\n", $1);
1151 $$.dclusage
= BWRITERDECLUSAGE_BLENDWEIGHT
;
1153 | USAGE_BLENDINDICES
1155 TRACE
("dcl_blendindices%u\n", $1);
1157 $$.dclusage
= BWRITERDECLUSAGE_BLENDINDICES
;
1161 TRACE
("dcl_normal%u\n", $1);
1163 $$.dclusage
= BWRITERDECLUSAGE_NORMAL
;
1167 TRACE
("dcl_psize%u\n", $1);
1169 $$.dclusage
= BWRITERDECLUSAGE_PSIZE
;
1173 TRACE
("dcl_texcoord%u\n", $1);
1175 $$.dclusage
= BWRITERDECLUSAGE_TEXCOORD
;
1179 TRACE
("dcl_tangent%u\n", $1);
1181 $$.dclusage
= BWRITERDECLUSAGE_TANGENT
;
1185 TRACE
("dcl_binormal%u\n", $1);
1187 $$.dclusage
= BWRITERDECLUSAGE_BINORMAL
;
1191 TRACE
("dcl_tessfactor%u\n", $1);
1193 $$.dclusage
= BWRITERDECLUSAGE_TESSFACTOR
;
1197 TRACE
("dcl_positiont%u\n", $1);
1199 $$.dclusage
= BWRITERDECLUSAGE_POSITIONT
;
1203 TRACE
("dcl_color%u\n", $1);
1205 $$.dclusage
= BWRITERDECLUSAGE_COLOR
;
1209 TRACE
("dcl_fog%u\n", $1);
1211 $$.dclusage
= BWRITERDECLUSAGE_FOG
;
1215 TRACE
("dcl_depth%u\n", $1);
1217 $$.dclusage
= BWRITERDECLUSAGE_DEPTH
;
1221 TRACE
("dcl_sample%u\n", $1);
1223 $$.dclusage
= BWRITERDECLUSAGE_SAMPLE
;
1226 sampdcl: SAMPTYPE_1D
1236 $$
= BWRITERSTT_CUBE
;
1240 $$
= BWRITERSTT_VOLUME
;
1243 predicate: '(' REG_PREDICATE swizzle
')'
1245 $$.type
= BWRITERSPR_PREDICATE
;
1248 $$.srcmod
= BWRITERSPSM_NONE
;
1251 |
'(' SMOD_NOT REG_PREDICATE swizzle
')'
1253 $$.type
= BWRITERSPR_PREDICATE
;
1256 $$.srcmod
= BWRITERSPSM_NOT
;
1262 void asmshader_error
(char const *s
) {
1263 asmparser_message
(&asm_ctx
, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no
, s
);
1264 set_parse_status
(&asm_ctx
, PARSE_ERR
);
1267 /* Error reporting function */
1268 void asmparser_message
(struct asm_parser
*ctx
, const char *fmt
, ...
) {
1273 if
(ctx
->messagecapacity
== 0) {
1274 ctx
->messages
= asm_alloc
(MESSAGEBUFFER_INITIAL_SIZE
);
1275 if
(ctx
->messages
== NULL
) {
1276 ERR
("Error allocating memory for parser messages\n");
1279 ctx
->messagecapacity
= MESSAGEBUFFER_INITIAL_SIZE
;
1283 va_start
(args
, fmt
);
1284 rc
= vsnprintf
(ctx
->messages
+ ctx
->messagesize
,
1285 ctx
->messagecapacity
- ctx
->messagesize
, fmt
, args
);
1288 if
(rc
< 0 ||
/* C89 */
1289 rc
>= ctx
->messagecapacity
- ctx
->messagesize
) { /* C99 */
1290 /* Resize the buffer */
1291 newsize
= ctx
->messagecapacity
* 2;
1292 newbuffer
= asm_realloc
(ctx
->messages
, newsize
);
1293 if
(newbuffer
== NULL
){
1294 ERR
("Error reallocating memory for parser messages\n");
1297 ctx
->messages
= newbuffer
;
1298 ctx
->messagecapacity
= newsize
;
1300 ctx
->messagesize
+= rc
;
1306 /* New status is the worst between current status and parameter value */
1307 void set_parse_status
(struct asm_parser
*ctx
, enum parse_status status
) {
1308 if
(status
== PARSE_ERR
) ctx
->status
= PARSE_ERR
;
1309 else if
(status
== PARSE_WARN
&& ctx
->status
== PARSE_SUCCESS
) ctx
->status
= PARSE_WARN
;
1312 struct bwriter_shader
*parse_asm_shader
(char **messages
) {
1313 struct bwriter_shader
*ret
= NULL
;
1315 asm_ctx.shader
= NULL
;
1316 asm_ctx.status
= PARSE_SUCCESS
;
1317 asm_ctx.messagesize
= asm_ctx.messagecapacity
= 0;
1318 asm_ctx.line_no
= 1;
1322 if
(asm_ctx.status
!= PARSE_ERR
) ret
= asm_ctx.shader
;
1323 else if
(asm_ctx.shader
) SlDeleteShader
(asm_ctx.shader
);
1326 if
(asm_ctx.messagesize
) {
1327 /* Shrink the buffer to the used size */
1328 *messages
= asm_realloc
(asm_ctx.messages
, asm_ctx.messagesize
+ 1);
1330 ERR
("Out of memory, no messages reported\n");
1331 asm_free
(asm_ctx.messages
);
1337 if
(asm_ctx.messagecapacity
) asm_free
(asm_ctx.messages
);