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"
28 #include "asmshader.tab.h"
32 WINE_DEFAULT_DEBUG_CHANNEL
(asmshader
);
34 struct asm_parser asm_ctx
;
36 /* Needed lexer functions declarations */
37 void asmshader_error
(const char *s
);
38 int asmshader_lex
(void);
40 void set_rel_reg
(struct shader_reg
*reg
, struct rel_reg
*rel
) {
48 struct shader_reg reg
;
59 struct rel_reg rel_reg
;
60 struct src_regs sregs
;
63 /* Common instructions between vertex and pixel shaders */
67 %token
<regnum
> REG_TEMP
68 %token
<regnum
> REG_CONSTFLOAT
91 %type
<swizzle
> swizzle
92 %type
<modshift
> omods
93 %type
<rel_reg
> rel_reg
98 shader: version_marker instructions
100 asm_ctx.funcs
->end
(&asm_ctx
);
103 version_marker: VER_VS10
105 TRACE
("Vertex shader 1.0\n");
106 set_parse_status
(&asm_ctx
, PARSE_ERR
);
111 TRACE
("Vertex shader 1.1\n");
112 set_parse_status
(&asm_ctx
, PARSE_ERR
);
117 TRACE
("Vertex shader 2.0\n");
118 set_parse_status
(&asm_ctx
, PARSE_ERR
);
123 TRACE
("Vertex shader 2.x\n");
124 set_parse_status
(&asm_ctx
, PARSE_ERR
);
129 TRACE
("Vertex shader 3.0\n");
130 create_vs30_parser
(&asm_ctx
);
134 TRACE
("Pixel shader 1.0\n");
135 set_parse_status
(&asm_ctx
, PARSE_ERR
);
140 TRACE
("Pixel shader 1.1\n");
141 set_parse_status
(&asm_ctx
, PARSE_ERR
);
146 TRACE
("Pixel shader 1.2\n");
147 set_parse_status
(&asm_ctx
, PARSE_ERR
);
152 TRACE
("Pixel shader 1.3\n");
153 set_parse_status
(&asm_ctx
, PARSE_ERR
);
158 TRACE
("Pixel shader 1.4\n");
159 set_parse_status
(&asm_ctx
, PARSE_ERR
);
164 TRACE
("Pixel shader 2.0\n");
165 set_parse_status
(&asm_ctx
, PARSE_ERR
);
170 TRACE
("Pixel shader 2.x\n");
171 set_parse_status
(&asm_ctx
, PARSE_ERR
);
176 TRACE
("Pixel shader 3.0\n");
177 set_parse_status
(&asm_ctx
, PARSE_ERR
);
181 instructions: /* empty */
182 | instructions complexinstr
187 complexinstr: instruction
192 instruction: INSTR_MOV omods dreg
',' sregs
195 asm_ctx.funcs
->instr
(&asm_ctx
, BWRITERSIO_MOV
, $2.mod
, $2.shift
, 0, &$3, &$5, 1);
198 dreg: dreg_name rel_reg
200 $$.regnum
= $1.regnum
;
202 $$.writemask
= BWRITERSP_WRITEMASK_ALL
;
203 $$.srcmod
= BWRITERSPSM_NONE
;
204 set_rel_reg
(&$$
, &$2);
209 $$.regnum
= $1; $$.type
= BWRITERSPR_TEMP
;
214 $$
= BWRITERVS_NOSWIZZLE
;
215 TRACE
("Default swizzle: %08x\n", $$
);
231 if
($$.count
== MAX_SRC_REGS
){
232 asmparser_message
(&asm_ctx
, "Line %u: Too many source registers in this instruction\n",
234 set_parse_status
(&asm_ctx
, PARSE_ERR
);
237 $$.reg
[$$.count
++] = $3;
240 sreg: sreg_name rel_reg swizzle
243 $$.regnum
= $1.regnum
;
245 $$.srcmod
= BWRITERSPSM_NONE
;
246 set_rel_reg
(&$$
, &$2);
251 $$.has_rel_reg
= FALSE
;
252 $$.additional_offset
= 0;
257 $$.regnum
= $1; $$.type
= BWRITERSPR_TEMP
;
261 $$.regnum
= $1; $$.type
= BWRITERSPR_CONST
;
266 void asmshader_error
(char const *s
) {
267 asmparser_message
(&asm_ctx
, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no
, s
);
268 set_parse_status
(&asm_ctx
, PARSE_ERR
);
271 /* Error reporting function */
272 void asmparser_message
(struct asm_parser
*ctx
, const char *fmt
, ...
) {
277 if
(ctx
->messagecapacity
== 0) {
278 ctx
->messages
= asm_alloc
(MESSAGEBUFFER_INITIAL_SIZE
);
279 if
(ctx
->messages
== NULL
) {
280 ERR
("Error allocating memory for parser messages\n");
283 ctx
->messagecapacity
= MESSAGEBUFFER_INITIAL_SIZE
;
288 rc
= vsnprintf
(ctx
->messages
+ ctx
->messagesize
,
289 ctx
->messagecapacity
- ctx
->messagesize
, fmt
, args
);
292 if
(rc
< 0 ||
/* C89 */
293 rc
>= ctx
->messagecapacity
- ctx
->messagesize
) { /* C99 */
294 /* Resize the buffer */
295 newsize
= ctx
->messagecapacity
* 2;
296 newbuffer
= asm_realloc
(ctx
->messages
, newsize
);
297 if
(newbuffer
== NULL
){
298 ERR
("Error reallocating memory for parser messages\n");
301 ctx
->messages
= newbuffer
;
302 ctx
->messagecapacity
= newsize
;
304 ctx
->messagesize
+= rc
;
310 /* New status is the worst between current status and parameter value */
311 void set_parse_status
(struct asm_parser
*ctx
, enum parse_status status
) {
312 if
(status
== PARSE_ERR
) ctx
->status
= PARSE_ERR
;
313 else if
(status
== PARSE_WARN
&& ctx
->status
== PARSE_SUCCESS
) ctx
->status
= PARSE_WARN
;
316 struct bwriter_shader
*parse_asm_shader
(char **messages
) {
317 struct bwriter_shader
*ret
= NULL
;
319 asm_ctx.shader
= NULL
;
320 asm_ctx.status
= PARSE_SUCCESS
;
321 asm_ctx.messagesize
= asm_ctx.messagecapacity
= 0;
326 if
(asm_ctx.status
!= PARSE_ERR
) ret
= asm_ctx.shader
;
327 else if
(asm_ctx.shader
) SlDeleteShader
(asm_ctx.shader
);
330 if
(asm_ctx.messagesize
) {
331 /* Shrink the buffer to the used size */
332 *messages
= asm_realloc
(asm_ctx.messages
, asm_ctx.messagesize
+ 1);
334 ERR
("Out of memory, no messages reported\n");
335 asm_free
(asm_ctx.messages
);
341 if
(asm_ctx.messagecapacity
) asm_free
(asm_ctx.messages
);