mfreadwrite/reader: Add missing allocation check (Coverity).
[wine/zf.git] / dlls / d3dcompiler_43 / asmparser.c
blob7a901576181d2f32aa638fb96fc9235d58de0313
1 /*
2 * Direct3D asm shader parser
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 "wine/debug.h"
25 #include "d3dcompiler_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
28 WINE_DECLARE_DEBUG_CHANNEL(parsed_shader);
31 /* How to map vs 1.0 and 2.0 varyings to 3.0 ones
32 * oTx is mapped to ox, which happens to be an
33 * identical mapping since BWRITERSPR_TEXCRDOUT == BWRITERSPR_OUTPUT
34 * oPos, oFog and point size are mapped to general output regs as well.
35 * the vs 1.x and 2.x parser functions add varying declarations
36 * to the shader, and the 1.x and 2.x output functions check those varyings
38 #define OT0_REG 0
39 #define OT1_REG 1
40 #define OT2_REG 2
41 #define OT3_REG 3
42 #define OT4_REG 4
43 #define OT5_REG 5
44 #define OT6_REG 6
45 #define OT7_REG 7
46 #define OPOS_REG 8
47 #define OFOG_REG 9
48 #define OFOG_WRITEMASK BWRITERSP_WRITEMASK_0
49 #define OPTS_REG 9
50 #define OPTS_WRITEMASK BWRITERSP_WRITEMASK_1
51 #define OD0_REG 10
52 #define OD1_REG 11
54 /* Input color registers 0-1 are identically mapped */
55 #define C0_VARYING 0
56 #define C1_VARYING 1
57 #define T0_VARYING 2
58 #define T1_VARYING 3
59 #define T2_VARYING 4
60 #define T3_VARYING 5
61 #define T4_VARYING 6
62 #define T5_VARYING 7
63 #define T6_VARYING 8
64 #define T7_VARYING 9
66 /****************************************************************
67 * Common(non-version specific) shader parser control code *
68 ****************************************************************/
70 static void asmparser_end(struct asm_parser *This) {
71 TRACE("Finalizing shader\n");
74 static void asmparser_constF(struct asm_parser *This, DWORD reg, float x, float y, float z, float w) {
75 if(!This->shader) return;
76 TRACE("Adding float constant %u at pos %u\n", reg, This->shader->num_cf);
77 TRACE_(parsed_shader)("def c%u, %f, %f, %f, %f\n", reg, x, y, z, w);
78 if(!add_constF(This->shader, reg, x, y, z, w)) {
79 ERR("Out of memory\n");
80 set_parse_status(&This->status, PARSE_ERR);
84 static void asmparser_constB(struct asm_parser *This, DWORD reg, BOOL x) {
85 if(!This->shader) return;
86 TRACE("Adding boolean constant %u at pos %u\n", reg, This->shader->num_cb);
87 TRACE_(parsed_shader)("def b%u, %s\n", reg, x ? "true" : "false");
88 if(!add_constB(This->shader, reg, x)) {
89 ERR("Out of memory\n");
90 set_parse_status(&This->status, PARSE_ERR);
94 static void asmparser_constI(struct asm_parser *This, DWORD reg, INT x, INT y, INT z, INT w) {
95 if(!This->shader) return;
96 TRACE("Adding integer constant %u at pos %u\n", reg, This->shader->num_ci);
97 TRACE_(parsed_shader)("def i%u, %d, %d, %d, %d\n", reg, x, y, z, w);
98 if(!add_constI(This->shader, reg, x, y, z, w)) {
99 ERR("Out of memory\n");
100 set_parse_status(&This->status, PARSE_ERR);
104 static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num,
105 const struct shader_reg *reg) {
106 if(!This->shader) return;
107 if(This->shader->type == ST_PIXEL) {
108 asmparser_message(This, "Line %u: Output register declared in a pixel shader\n", This->line_no);
109 set_parse_status(&This->status, PARSE_ERR);
111 if(!record_declaration(This->shader, usage, num, 0, TRUE, reg->regnum, reg->u.writemask, FALSE)) {
112 ERR("Out of memory\n");
113 set_parse_status(&This->status, PARSE_ERR);
117 static void asmparser_dcl_output_unsupported(struct asm_parser *This, DWORD usage, DWORD num,
118 const struct shader_reg *reg) {
119 asmparser_message(This, "Line %u: Output declaration unsupported in this shader version\n", This->line_no);
120 set_parse_status(&This->status, PARSE_ERR);
123 static void asmparser_dcl_input(struct asm_parser *This, DWORD usage, DWORD num,
124 DWORD mod, const struct shader_reg *reg) {
125 struct instruction instr;
127 if(!This->shader) return;
128 if (mod && (This->shader->type != ST_PIXEL || This->shader->major_version != 3
129 || (mod != BWRITERSPDM_MSAMPCENTROID && mod != BWRITERSPDM_PARTIALPRECISION)))
131 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
132 set_parse_status(&This->status, PARSE_ERR);
133 return;
136 /* Check register type and modifiers */
137 instr.dstmod = mod;
138 instr.shift = 0;
139 This->funcs->dstreg(This, &instr, reg);
141 if(!record_declaration(This->shader, usage, num, mod, FALSE, reg->regnum, reg->u.writemask, FALSE)) {
142 ERR("Out of memory\n");
143 set_parse_status(&This->status, PARSE_ERR);
147 static void asmparser_dcl_input_ps_2(struct asm_parser *This, DWORD usage, DWORD num,
148 DWORD mod, const struct shader_reg *reg) {
149 struct instruction instr;
151 if(!This->shader) return;
152 instr.dstmod = mod;
153 instr.shift = 0;
154 This->funcs->dstreg(This, &instr, reg);
155 if(!record_declaration(This->shader, usage, num, mod, FALSE, instr.dst.regnum, instr.dst.u.writemask, FALSE)) {
156 ERR("Out of memory\n");
157 set_parse_status(&This->status, PARSE_ERR);
161 static void asmparser_dcl_input_unsupported(struct asm_parser *This,
162 DWORD usage, DWORD num, DWORD mod, const struct shader_reg *reg)
164 asmparser_message(This, "Line %u: Input declaration unsupported in this shader version\n", This->line_no);
165 set_parse_status(&This->status, PARSE_ERR);
168 static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype,
169 DWORD mod, DWORD regnum,
170 unsigned int line_no) {
171 if(!This->shader) return;
172 if (mod && (This->shader->type != ST_PIXEL || This->shader->major_version != 3
173 || (mod != BWRITERSPDM_MSAMPCENTROID && mod != BWRITERSPDM_PARTIALPRECISION)))
175 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
176 set_parse_status(&This->status, PARSE_ERR);
177 return;
179 if(!record_sampler(This->shader, samptype, mod, regnum)) {
180 ERR("Out of memory\n");
181 set_parse_status(&This->status, PARSE_ERR);
185 static void asmparser_dcl_sampler_unsupported(struct asm_parser *This,
186 DWORD samptype, DWORD mod, DWORD regnum, unsigned int line_no)
188 asmparser_message(This, "Line %u: Sampler declaration unsupported in this shader version\n", This->line_no);
189 set_parse_status(&This->status, PARSE_ERR);
192 static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift,
193 const struct shader_reg *dst,
194 const struct src_regs *srcs) {
195 struct instruction *instr;
197 if(!srcs || srcs->count != 3) {
198 asmparser_message(This, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This->line_no);
199 set_parse_status(&This->status, PARSE_ERR);
200 return;
203 instr = alloc_instr(3);
204 if(!instr) {
205 ERR("Error allocating memory for the instruction\n");
206 set_parse_status(&This->status, PARSE_ERR);
207 return;
210 instr->opcode = BWRITERSIO_SINCOS;
211 instr->dstmod = mod;
212 instr->shift = shift;
213 instr->comptype = 0;
215 This->funcs->dstreg(This, instr, dst);
216 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
217 This->funcs->srcreg(This, instr, 1, &srcs->reg[1]);
218 This->funcs->srcreg(This, instr, 2, &srcs->reg[2]);
220 if(!add_instruction(This->shader, instr)) {
221 ERR("Out of memory\n");
222 set_parse_status(&This->status, PARSE_ERR);
226 static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) {
227 struct shader_reg ret;
228 switch(reg->type) {
229 case BWRITERSPR_TEXTURE:
230 if(tex_varying) {
231 ret = *reg;
232 ret.type = BWRITERSPR_INPUT;
233 switch(reg->regnum) {
234 case 0: ret.regnum = T0_VARYING; break;
235 case 1: ret.regnum = T1_VARYING; break;
236 case 2: ret.regnum = T2_VARYING; break;
237 case 3: ret.regnum = T3_VARYING; break;
238 case 4: ret.regnum = T4_VARYING; break;
239 case 5: ret.regnum = T5_VARYING; break;
240 case 6: ret.regnum = T6_VARYING; break;
241 case 7: ret.regnum = T7_VARYING; break;
242 default:
243 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
244 return *reg;
246 return ret;
247 } else {
248 ret = *reg;
249 ret.type = BWRITERSPR_TEMP;
250 switch(reg->regnum) {
251 case 0: ret.regnum = T0_REG; break;
252 case 1: ret.regnum = T1_REG; break;
253 case 2: ret.regnum = T2_REG; break;
254 case 3: ret.regnum = T3_REG; break;
255 default:
256 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
257 return *reg;
259 return ret;
262 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
263 to 3.0 ones */
265 default: return *reg;
269 static void asmparser_texcoord(struct asm_parser *This, DWORD mod, DWORD shift,
270 const struct shader_reg *dst,
271 const struct src_regs *srcs) {
272 struct instruction *instr;
274 if(srcs) {
275 asmparser_message(This, "Line %u: Source registers in texcoord instruction\n", This->line_no);
276 set_parse_status(&This->status, PARSE_ERR);
277 return;
280 instr = alloc_instr(1);
281 if(!instr) {
282 ERR("Error allocating memory for the instruction\n");
283 set_parse_status(&This->status, PARSE_ERR);
284 return;
287 /* texcoord copies the texture coord data into a temporary register-like
288 * readable form. In newer shader models this equals a MOV from v0 to r0,
289 * record it as this.
291 instr->opcode = BWRITERSIO_MOV;
292 instr->dstmod = mod | BWRITERSPDM_SATURATE; /* texcoord clamps to [0;1] */
293 instr->shift = shift;
294 instr->comptype = 0;
296 This->funcs->dstreg(This, instr, dst);
297 /* The src reg needs special care */
298 instr->src[0] = map_oldps_register(dst, TRUE);
300 if(!add_instruction(This->shader, instr)) {
301 ERR("Out of memory\n");
302 set_parse_status(&This->status, PARSE_ERR);
306 static void asmparser_texcrd(struct asm_parser *This, DWORD mod, DWORD shift,
307 const struct shader_reg *dst,
308 const struct src_regs *srcs) {
309 struct instruction *instr;
311 if(!srcs || srcs->count != 1) {
312 asmparser_message(This, "Line %u: Wrong number of source registers in texcrd instruction\n", This->line_no);
313 set_parse_status(&This->status, PARSE_ERR);
314 return;
317 instr = alloc_instr(1);
318 if(!instr) {
319 ERR("Error allocating memory for the instruction\n");
320 set_parse_status(&This->status, PARSE_ERR);
321 return;
324 /* The job of texcrd is done by mov in later shader versions */
325 instr->opcode = BWRITERSIO_MOV;
326 instr->dstmod = mod;
327 instr->shift = shift;
328 instr->comptype = 0;
330 This->funcs->dstreg(This, instr, dst);
331 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
333 if(!add_instruction(This->shader, instr)) {
334 ERR("Out of memory\n");
335 set_parse_status(&This->status, PARSE_ERR);
339 static void asmparser_texkill(struct asm_parser *This,
340 const struct shader_reg *dst) {
341 struct instruction *instr = alloc_instr(0);
343 if(!instr) {
344 ERR("Error allocating memory for the instruction\n");
345 set_parse_status(&This->status, PARSE_ERR);
346 return;
349 instr->opcode = BWRITERSIO_TEXKILL;
350 instr->dstmod = 0;
351 instr->shift = 0;
352 instr->comptype = 0;
354 /* Do not run the dst register through the normal
355 * register conversion. If used with ps_1_0 to ps_1_3
356 * the texture coordinate from that register is used,
357 * not the temporary register value. In ps_1_4 and
358 * ps_2_0 t0 is always a varying and temporaries can
359 * be used with texkill.
361 instr->dst = map_oldps_register(dst, TRUE);
362 instr->has_dst = TRUE;
364 if(!add_instruction(This->shader, instr)) {
365 ERR("Out of memory\n");
366 set_parse_status(&This->status, PARSE_ERR);
370 static void asmparser_texhelper(struct asm_parser *This, DWORD mod, DWORD shift,
371 const struct shader_reg *dst,
372 const struct shader_reg *src0) {
373 struct instruction *instr = alloc_instr(2);
375 if(!instr) {
376 ERR("Error allocating memory for the instruction\n");
377 set_parse_status(&This->status, PARSE_ERR);
378 return;
381 instr->opcode = BWRITERSIO_TEX;
382 instr->dstmod = mod;
383 instr->shift = shift;
384 instr->comptype = 0;
385 /* The dest register can be mapped normally to a temporary register */
386 This->funcs->dstreg(This, instr, dst);
387 /* Use the src passed as parameter by the specific instruction handler */
388 instr->src[0] = *src0;
390 /* The 2nd source register is the sampler register with the
391 * destination's regnum
393 ZeroMemory(&instr->src[1], sizeof(instr->src[1]));
394 instr->src[1].type = BWRITERSPR_SAMPLER;
395 instr->src[1].regnum = dst->regnum;
396 instr->src[1].u.swizzle = BWRITERVS_NOSWIZZLE;
397 instr->src[1].srcmod = BWRITERSPSM_NONE;
398 instr->src[1].rel_reg = NULL;
400 if(!add_instruction(This->shader, instr)) {
401 ERR("Out of memory\n");
402 set_parse_status(&This->status, PARSE_ERR);
406 static void asmparser_tex(struct asm_parser *This, DWORD mod, DWORD shift,
407 const struct shader_reg *dst) {
408 struct shader_reg src;
410 /* The first source register is the varying containing the coordinate */
411 src = map_oldps_register(dst, TRUE);
412 asmparser_texhelper(This, mod, shift, dst, &src);
415 static void asmparser_texld14(struct asm_parser *This, DWORD mod, DWORD shift,
416 const struct shader_reg *dst,
417 const struct src_regs *srcs) {
418 struct instruction *instr;
420 if(!srcs || srcs->count != 1) {
421 asmparser_message(This, "Line %u: texld (PS 1.4) has a wrong number of source registers\n", This->line_no);
422 set_parse_status(&This->status, PARSE_ERR);
423 return;
426 instr = alloc_instr(2);
427 if(!instr) {
428 ERR("Error allocating memory for the instruction\n");
429 set_parse_status(&This->status, PARSE_ERR);
430 return;
433 /* This code is recording a texld instruction, not tex. However,
434 * texld borrows the opcode of tex
436 instr->opcode = BWRITERSIO_TEX;
437 instr->dstmod = mod;
438 instr->shift = shift;
439 instr->comptype = 0;
441 This->funcs->dstreg(This, instr, dst);
442 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
444 /* The 2nd source register is the sampler register with the
445 * destination's regnum
447 ZeroMemory(&instr->src[1], sizeof(instr->src[1]));
448 instr->src[1].type = BWRITERSPR_SAMPLER;
449 instr->src[1].regnum = dst->regnum;
450 instr->src[1].u.swizzle = BWRITERVS_NOSWIZZLE;
451 instr->src[1].srcmod = BWRITERSPSM_NONE;
452 instr->src[1].rel_reg = NULL;
454 if(!add_instruction(This->shader, instr)) {
455 ERR("Out of memory\n");
456 set_parse_status(&This->status, PARSE_ERR);
460 static void asmparser_texreg2ar(struct asm_parser *This, DWORD mod, DWORD shift,
461 const struct shader_reg *dst,
462 const struct shader_reg *src0) {
463 struct shader_reg src;
465 src = map_oldps_register(src0, FALSE);
466 /* Supply the correct swizzle */
467 src.u.swizzle = BWRITERVS_X_W | BWRITERVS_Y_X | BWRITERVS_Z_X | BWRITERVS_W_X;
468 asmparser_texhelper(This, mod, shift, dst, &src);
471 static void asmparser_texreg2gb(struct asm_parser *This, DWORD mod, DWORD shift,
472 const struct shader_reg *dst,
473 const struct shader_reg *src0) {
474 struct shader_reg src;
476 src = map_oldps_register(src0, FALSE);
477 /* Supply the correct swizzle */
478 src.u.swizzle = BWRITERVS_X_Y | BWRITERVS_Y_Z | BWRITERVS_Z_Z | BWRITERVS_W_Z;
479 asmparser_texhelper(This, mod, shift, dst, &src);
482 static void asmparser_texreg2rgb(struct asm_parser *This, DWORD mod, DWORD shift,
483 const struct shader_reg *dst,
484 const struct shader_reg *src0) {
485 struct shader_reg src;
487 src = map_oldps_register(src0, FALSE);
488 /* Supply the correct swizzle */
489 src.u.swizzle = BWRITERVS_X_X | BWRITERVS_Y_Y | BWRITERVS_Z_Z | BWRITERVS_W_Z;
490 asmparser_texhelper(This, mod, shift, dst, &src);
493 /* Complex pixel shader 1.3 instructions like texm3x3tex are tricky - the
494 * bytecode writer works instruction by instruction, so we can't properly
495 * convert these from/to equivalent ps_3_0 instructions. Then simply keep using
496 * the ps_1_3 opcodes and just adapt the registers in the common fashion (i.e.
497 * go through asmparser_instr).
500 static void asmparser_instr(struct asm_parser *This, DWORD opcode, DWORD mod, DWORD shift,
501 enum bwriter_comparison_type comp, const struct shader_reg *dst,
502 const struct src_regs *srcs, int expectednsrcs)
504 struct bwriter_shader *shader = This->shader;
505 struct instruction *instr;
506 unsigned int i;
507 BOOL firstreg = TRUE;
508 unsigned int src_count = srcs ? srcs->count : 0;
510 if(!This->shader) return;
512 TRACE_(parsed_shader)("%s%s%s%s ", debug_print_opcode(opcode),
513 debug_print_dstmod(mod),
514 debug_print_shift(shift),
515 debug_print_comp(comp));
516 if(dst) {
517 TRACE_(parsed_shader)("%s", debug_print_dstreg(dst));
518 firstreg = FALSE;
520 for(i = 0; i < src_count; i++) {
521 if(!firstreg) TRACE_(parsed_shader)(", ");
522 else firstreg = FALSE;
523 TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i]));
525 TRACE_(parsed_shader)("\n");
527 /* Check for instructions with different syntaxes in different shader versions */
528 switch(opcode) {
529 case BWRITERSIO_SINCOS:
530 /* The syntax changes between vs 2 and the other shader versions */
531 if (This->shader->type == ST_VERTEX && This->shader->major_version == 2)
533 asmparser_sincos(This, mod, shift, dst, srcs);
534 return;
536 /* Use the default handling */
537 break;
538 case BWRITERSIO_TEXCOORD:
539 /* texcoord/texcrd are two instructions present only in PS <= 1.3 and PS 1.4 respectively */
540 if (shader->type == ST_PIXEL && shader->major_version == 1 && shader->minor_version == 4)
541 asmparser_texcrd(This, mod, shift, dst, srcs);
542 else
543 asmparser_texcoord(This, mod, shift, dst, srcs);
544 return;
545 case BWRITERSIO_TEX:
546 /* this encodes both the tex PS 1.x instruction and the
547 texld 1.4/2.0+ instruction */
548 if (shader->type == ST_PIXEL && shader->major_version == 1)
550 if (shader->minor_version < 4)
551 asmparser_tex(This, mod, shift, dst);
552 else
553 asmparser_texld14(This, mod, shift, dst, srcs);
554 return;
556 /* else fallback to the standard behavior */
557 break;
560 if(src_count != expectednsrcs) {
561 asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no);
562 set_parse_status(&This->status, PARSE_ERR);
563 return;
566 /* Handle PS 1.x instructions, "regularizing" them */
567 switch(opcode) {
568 case BWRITERSIO_TEXKILL:
569 asmparser_texkill(This, dst);
570 return;
571 case BWRITERSIO_TEXREG2AR:
572 asmparser_texreg2ar(This, mod, shift, dst, &srcs->reg[0]);
573 return;
574 case BWRITERSIO_TEXREG2GB:
575 asmparser_texreg2gb(This, mod, shift, dst, &srcs->reg[0]);
576 return;
577 case BWRITERSIO_TEXREG2RGB:
578 asmparser_texreg2rgb(This, mod, shift, dst, &srcs->reg[0]);
579 return;
582 instr = alloc_instr(src_count);
583 if(!instr) {
584 ERR("Error allocating memory for the instruction\n");
585 set_parse_status(&This->status, PARSE_ERR);
586 return;
589 instr->opcode = opcode;
590 instr->dstmod = mod;
591 instr->shift = shift;
592 instr->comptype = comp;
593 if(dst) This->funcs->dstreg(This, instr, dst);
594 for(i = 0; i < src_count; i++) {
595 This->funcs->srcreg(This, instr, i, &srcs->reg[i]);
598 if(!add_instruction(This->shader, instr)) {
599 ERR("Out of memory\n");
600 set_parse_status(&This->status, PARSE_ERR);
604 static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
605 struct shader_reg ret;
606 switch(reg->type) {
607 case BWRITERSPR_RASTOUT:
608 ret = *reg;
609 ret.type = BWRITERSPR_OUTPUT;
610 switch(reg->regnum) {
611 case BWRITERSRO_POSITION:
612 ret.regnum = OPOS_REG;
613 break;
614 case BWRITERSRO_FOG:
615 ret.regnum = OFOG_REG;
616 ret.u.writemask = OFOG_WRITEMASK;
617 break;
618 case BWRITERSRO_POINT_SIZE:
619 ret.regnum = OPTS_REG;
620 ret.u.writemask = OPTS_WRITEMASK;
621 break;
622 default:
623 FIXME("Unhandled RASTOUT register %u\n", reg->regnum);
624 return *reg;
626 return ret;
628 case BWRITERSPR_TEXCRDOUT:
629 ret = *reg;
630 ret.type = BWRITERSPR_OUTPUT;
631 switch(reg->regnum) {
632 case 0: ret.regnum = OT0_REG; break;
633 case 1: ret.regnum = OT1_REG; break;
634 case 2: ret.regnum = OT2_REG; break;
635 case 3: ret.regnum = OT3_REG; break;
636 case 4: ret.regnum = OT4_REG; break;
637 case 5: ret.regnum = OT5_REG; break;
638 case 6: ret.regnum = OT6_REG; break;
639 case 7: ret.regnum = OT7_REG; break;
640 default:
641 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum);
642 return *reg;
644 return ret;
646 case BWRITERSPR_ATTROUT:
647 ret = *reg;
648 ret.type = BWRITERSPR_OUTPUT;
649 switch(reg->regnum) {
650 case 0: ret.regnum = OD0_REG; break;
651 case 1: ret.regnum = OD1_REG; break;
652 default:
653 FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum);
654 return *reg;
656 return ret;
658 default: return *reg;
662 /* Checks for unsupported source modifiers in VS (all versions) or
663 PS 2.0 and newer */
664 static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) {
665 if(srcmod == BWRITERSPSM_BIAS || srcmod == BWRITERSPSM_BIASNEG ||
666 srcmod == BWRITERSPSM_SIGN || srcmod == BWRITERSPSM_SIGNNEG ||
667 srcmod == BWRITERSPSM_COMP || srcmod == BWRITERSPSM_X2 ||
668 srcmod == BWRITERSPSM_X2NEG || srcmod == BWRITERSPSM_DZ ||
669 srcmod == BWRITERSPSM_DW) {
670 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
671 This->line_no,
672 debug_print_srcmod(srcmod));
673 set_parse_status(&This->status, PARSE_ERR);
677 static void check_abs_srcmod(struct asm_parser *This, DWORD srcmod) {
678 if(srcmod == BWRITERSPSM_ABS || srcmod == BWRITERSPSM_ABSNEG) {
679 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
680 This->line_no,
681 debug_print_srcmod(srcmod));
682 set_parse_status(&This->status, PARSE_ERR);
686 static void check_loop_swizzle(struct asm_parser *This,
687 const struct shader_reg *src) {
688 if((src->type == BWRITERSPR_LOOP && src->u.swizzle != BWRITERVS_NOSWIZZLE) ||
689 (src->rel_reg && src->rel_reg->type == BWRITERSPR_LOOP &&
690 src->rel_reg->u.swizzle != BWRITERVS_NOSWIZZLE)) {
691 asmparser_message(This, "Line %u: Swizzle not allowed on aL register\n", This->line_no);
692 set_parse_status(&This->status, PARSE_ERR);
696 static void check_shift_dstmod(struct asm_parser *This, DWORD shift) {
697 if(shift != 0) {
698 asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n",
699 This->line_no);
700 set_parse_status(&This->status, PARSE_ERR);
704 static void check_ps_dstmod(struct asm_parser *This, DWORD dstmod) {
705 if(dstmod == BWRITERSPDM_PARTIALPRECISION ||
706 dstmod == BWRITERSPDM_MSAMPCENTROID) {
707 asmparser_message(This, "Line %u: Instruction modifier %s not supported in this shader version\n",
708 This->line_no,
709 debug_print_dstmod(dstmod));
710 set_parse_status(&This->status, PARSE_ERR);
714 struct allowed_reg_type {
715 DWORD type;
716 DWORD count;
717 BOOL reladdr;
720 static BOOL check_reg_type(const struct shader_reg *reg,
721 const struct allowed_reg_type *allowed) {
722 unsigned int i = 0;
724 while(allowed[i].type != ~0U) {
725 if(reg->type == allowed[i].type) {
726 if(reg->rel_reg) {
727 if(allowed[i].reladdr)
728 return TRUE; /* The relative addressing register
729 can have a negative value, we
730 can't check the register index */
731 return FALSE;
733 if(reg->regnum < allowed[i].count) return TRUE;
734 return FALSE;
736 i++;
738 return FALSE;
741 /* Native assembler doesn't do separate checks for src and dst registers */
742 static const struct allowed_reg_type vs_1_reg_allowed[] = {
743 { BWRITERSPR_TEMP, 12, FALSE },
744 { BWRITERSPR_INPUT, 16, FALSE },
745 { BWRITERSPR_CONST, ~0U, TRUE },
746 { BWRITERSPR_ADDR, 1, FALSE },
747 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
748 { BWRITERSPR_ATTROUT, 2, FALSE },
749 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
750 { ~0U, 0 } /* End tag */
753 /* struct instruction *asmparser_srcreg
755 * Records a source register in the instruction and does shader version
756 * specific checks and modifications on it
758 * Parameters:
759 * This: Shader parser instance
760 * instr: instruction to store the register in
761 * num: Number of source register
762 * src: Pointer to source the register structure. The caller can free
763 * it afterwards
765 static void asmparser_srcreg_vs_1(struct asm_parser *This,
766 struct instruction *instr, int num,
767 const struct shader_reg *src) {
768 struct shader_reg reg;
770 if(!check_reg_type(src, vs_1_reg_allowed)) {
771 asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n",
772 This->line_no,
773 debug_print_srcreg(src));
774 set_parse_status(&This->status, PARSE_ERR);
776 check_legacy_srcmod(This, src->srcmod);
777 check_abs_srcmod(This, src->srcmod);
778 reg = map_oldvs_register(src);
779 instr->src[num] = reg;
782 static const struct allowed_reg_type vs_2_reg_allowed[] = {
783 { BWRITERSPR_TEMP, 12, FALSE },
784 { BWRITERSPR_INPUT, 16, FALSE },
785 { BWRITERSPR_CONST, ~0U, TRUE },
786 { BWRITERSPR_ADDR, 1, FALSE },
787 { BWRITERSPR_CONSTBOOL, 16, FALSE },
788 { BWRITERSPR_CONSTINT, 16, FALSE },
789 { BWRITERSPR_LOOP, 1, FALSE },
790 { BWRITERSPR_LABEL, 2048, FALSE },
791 { BWRITERSPR_PREDICATE, 1, FALSE },
792 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
793 { BWRITERSPR_ATTROUT, 2, FALSE },
794 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
795 { ~0U, 0 } /* End tag */
798 static void asmparser_srcreg_vs_2(struct asm_parser *This,
799 struct instruction *instr, int num,
800 const struct shader_reg *src) {
801 struct shader_reg reg;
803 if(!check_reg_type(src, vs_2_reg_allowed)) {
804 asmparser_message(This, "Line %u: Source register %s not supported in VS 2\n",
805 This->line_no,
806 debug_print_srcreg(src));
807 set_parse_status(&This->status, PARSE_ERR);
809 check_loop_swizzle(This, src);
810 check_legacy_srcmod(This, src->srcmod);
811 check_abs_srcmod(This, src->srcmod);
812 reg = map_oldvs_register(src);
813 instr->src[num] = reg;
816 static const struct allowed_reg_type vs_3_reg_allowed[] = {
817 { BWRITERSPR_TEMP, 32, FALSE },
818 { BWRITERSPR_INPUT, 16, TRUE },
819 { BWRITERSPR_CONST, ~0U, TRUE },
820 { BWRITERSPR_ADDR, 1, FALSE },
821 { BWRITERSPR_CONSTBOOL, 16, FALSE },
822 { BWRITERSPR_CONSTINT, 16, FALSE },
823 { BWRITERSPR_LOOP, 1, FALSE },
824 { BWRITERSPR_LABEL, 2048, FALSE },
825 { BWRITERSPR_PREDICATE, 1, FALSE },
826 { BWRITERSPR_SAMPLER, 4, FALSE },
827 { BWRITERSPR_OUTPUT, 12, TRUE },
828 { ~0U, 0 } /* End tag */
831 static void asmparser_srcreg_vs_3(struct asm_parser *This,
832 struct instruction *instr, int num,
833 const struct shader_reg *src) {
834 if(!check_reg_type(src, vs_3_reg_allowed)) {
835 asmparser_message(This, "Line %u: Source register %s not supported in VS 3.0\n",
836 This->line_no,
837 debug_print_srcreg(src));
838 set_parse_status(&This->status, PARSE_ERR);
840 check_loop_swizzle(This, src);
841 check_legacy_srcmod(This, src->srcmod);
842 instr->src[num] = *src;
845 static const struct allowed_reg_type ps_1_0123_reg_allowed[] = {
846 { BWRITERSPR_CONST, 8, FALSE },
847 { BWRITERSPR_TEMP, 2, FALSE },
848 { BWRITERSPR_TEXTURE, 4, FALSE },
849 { BWRITERSPR_INPUT, 2, FALSE },
850 { ~0U, 0 } /* End tag */
853 static void asmparser_srcreg_ps_1_0123(struct asm_parser *This,
854 struct instruction *instr, int num,
855 const struct shader_reg *src) {
856 struct shader_reg reg;
858 if(!check_reg_type(src, ps_1_0123_reg_allowed)) {
859 asmparser_message(This, "Line %u: Source register %s not supported in <== PS 1.3\n",
860 This->line_no,
861 debug_print_srcreg(src));
862 set_parse_status(&This->status, PARSE_ERR);
864 check_abs_srcmod(This, src->srcmod);
865 reg = map_oldps_register(src, FALSE);
866 instr->src[num] = reg;
869 static const struct allowed_reg_type ps_1_4_reg_allowed[] = {
870 { BWRITERSPR_CONST, 8, FALSE },
871 { BWRITERSPR_TEMP, 6, FALSE },
872 { BWRITERSPR_TEXTURE, 6, FALSE },
873 { BWRITERSPR_INPUT, 2, FALSE },
874 { ~0U, 0 } /* End tag */
877 static void asmparser_srcreg_ps_1_4(struct asm_parser *This,
878 struct instruction *instr, int num,
879 const struct shader_reg *src) {
880 struct shader_reg reg;
882 if(!check_reg_type(src, ps_1_4_reg_allowed)) {
883 asmparser_message(This, "Line %u: Source register %s not supported in PS 1.4\n",
884 This->line_no,
885 debug_print_srcreg(src));
886 set_parse_status(&This->status, PARSE_ERR);
888 check_abs_srcmod(This, src->srcmod);
889 reg = map_oldps_register(src, TRUE);
890 instr->src[num] = reg;
893 static const struct allowed_reg_type ps_2_0_reg_allowed[] = {
894 { BWRITERSPR_INPUT, 2, FALSE },
895 { BWRITERSPR_TEMP, 32, FALSE },
896 { BWRITERSPR_CONST, 32, FALSE },
897 { BWRITERSPR_CONSTINT, 16, FALSE },
898 { BWRITERSPR_CONSTBOOL, 16, FALSE },
899 { BWRITERSPR_SAMPLER, 16, FALSE },
900 { BWRITERSPR_TEXTURE, 8, FALSE },
901 { BWRITERSPR_COLOROUT, 4, FALSE },
902 { BWRITERSPR_DEPTHOUT, 1, FALSE },
903 { ~0U, 0 } /* End tag */
906 static void asmparser_srcreg_ps_2(struct asm_parser *This,
907 struct instruction *instr, int num,
908 const struct shader_reg *src) {
909 struct shader_reg reg;
911 if(!check_reg_type(src, ps_2_0_reg_allowed)) {
912 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.0\n",
913 This->line_no,
914 debug_print_srcreg(src));
915 set_parse_status(&This->status, PARSE_ERR);
917 check_legacy_srcmod(This, src->srcmod);
918 check_abs_srcmod(This, src->srcmod);
919 reg = map_oldps_register(src, TRUE);
920 instr->src[num] = reg;
923 static const struct allowed_reg_type ps_2_x_reg_allowed[] = {
924 { BWRITERSPR_INPUT, 2, FALSE },
925 { BWRITERSPR_TEMP, 32, FALSE },
926 { BWRITERSPR_CONST, 32, FALSE },
927 { BWRITERSPR_CONSTINT, 16, FALSE },
928 { BWRITERSPR_CONSTBOOL, 16, FALSE },
929 { BWRITERSPR_PREDICATE, 1, FALSE },
930 { BWRITERSPR_SAMPLER, 16, FALSE },
931 { BWRITERSPR_TEXTURE, 8, FALSE },
932 { BWRITERSPR_LABEL, 2048, FALSE },
933 { BWRITERSPR_COLOROUT, 4, FALSE },
934 { BWRITERSPR_DEPTHOUT, 1, FALSE },
935 { ~0U, 0 } /* End tag */
938 static void asmparser_srcreg_ps_2_x(struct asm_parser *This,
939 struct instruction *instr, int num,
940 const struct shader_reg *src) {
941 struct shader_reg reg;
943 if(!check_reg_type(src, ps_2_x_reg_allowed)) {
944 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.x\n",
945 This->line_no,
946 debug_print_srcreg(src));
947 set_parse_status(&This->status, PARSE_ERR);
949 check_legacy_srcmod(This, src->srcmod);
950 check_abs_srcmod(This, src->srcmod);
951 reg = map_oldps_register(src, TRUE);
952 instr->src[num] = reg;
955 static const struct allowed_reg_type ps_3_reg_allowed[] = {
956 { BWRITERSPR_INPUT, 10, TRUE },
957 { BWRITERSPR_TEMP, 32, FALSE },
958 { BWRITERSPR_CONST, 224, FALSE },
959 { BWRITERSPR_CONSTINT, 16, FALSE },
960 { BWRITERSPR_CONSTBOOL, 16, FALSE },
961 { BWRITERSPR_PREDICATE, 1, FALSE },
962 { BWRITERSPR_SAMPLER, 16, FALSE },
963 { BWRITERSPR_MISCTYPE, 2, FALSE }, /* vPos and vFace */
964 { BWRITERSPR_LOOP, 1, FALSE },
965 { BWRITERSPR_LABEL, 2048, FALSE },
966 { BWRITERSPR_COLOROUT, 4, FALSE },
967 { BWRITERSPR_DEPTHOUT, 1, FALSE },
968 { ~0U, 0 } /* End tag */
971 static void asmparser_srcreg_ps_3(struct asm_parser *This,
972 struct instruction *instr, int num,
973 const struct shader_reg *src) {
974 if(!check_reg_type(src, ps_3_reg_allowed)) {
975 asmparser_message(This, "Line %u: Source register %s not supported in PS 3.0\n",
976 This->line_no,
977 debug_print_srcreg(src));
978 set_parse_status(&This->status, PARSE_ERR);
980 check_loop_swizzle(This, src);
981 check_legacy_srcmod(This, src->srcmod);
982 instr->src[num] = *src;
985 static void asmparser_dstreg_vs_1(struct asm_parser *This,
986 struct instruction *instr,
987 const struct shader_reg *dst) {
988 struct shader_reg reg;
990 if(!check_reg_type(dst, vs_1_reg_allowed)) {
991 asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\n",
992 This->line_no,
993 debug_print_dstreg(dst));
994 set_parse_status(&This->status, PARSE_ERR);
996 check_ps_dstmod(This, instr->dstmod);
997 check_shift_dstmod(This, instr->shift);
998 reg = map_oldvs_register(dst);
999 instr->dst = reg;
1000 instr->has_dst = TRUE;
1003 static void asmparser_dstreg_vs_2(struct asm_parser *This,
1004 struct instruction *instr,
1005 const struct shader_reg *dst) {
1006 struct shader_reg reg;
1008 if(!check_reg_type(dst, vs_2_reg_allowed)) {
1009 asmparser_message(This, "Line %u: Destination register %s not supported in VS 2.0\n",
1010 This->line_no,
1011 debug_print_dstreg(dst));
1012 set_parse_status(&This->status, PARSE_ERR);
1014 check_ps_dstmod(This, instr->dstmod);
1015 check_shift_dstmod(This, instr->shift);
1016 reg = map_oldvs_register(dst);
1017 instr->dst = reg;
1018 instr->has_dst = TRUE;
1021 static void asmparser_dstreg_vs_3(struct asm_parser *This,
1022 struct instruction *instr,
1023 const struct shader_reg *dst) {
1024 if(!check_reg_type(dst, vs_3_reg_allowed)) {
1025 asmparser_message(This, "Line %u: Destination register %s not supported in VS 3.0\n",
1026 This->line_no,
1027 debug_print_dstreg(dst));
1028 set_parse_status(&This->status, PARSE_ERR);
1030 check_ps_dstmod(This, instr->dstmod);
1031 check_shift_dstmod(This, instr->shift);
1032 instr->dst = *dst;
1033 instr->has_dst = TRUE;
1036 static void asmparser_dstreg_ps_1_0123(struct asm_parser *This,
1037 struct instruction *instr,
1038 const struct shader_reg *dst) {
1039 struct shader_reg reg;
1041 if(!check_reg_type(dst, ps_1_0123_reg_allowed)) {
1042 asmparser_message(This, "Line %u: Destination register %s not supported in PS 1\n",
1043 This->line_no,
1044 debug_print_dstreg(dst));
1045 set_parse_status(&This->status, PARSE_ERR);
1047 reg = map_oldps_register(dst, FALSE);
1048 instr->dst = reg;
1049 instr->has_dst = TRUE;
1052 static void asmparser_dstreg_ps_1_4(struct asm_parser *This,
1053 struct instruction *instr,
1054 const struct shader_reg *dst) {
1055 struct shader_reg reg;
1057 if(!check_reg_type(dst, ps_1_4_reg_allowed)) {
1058 asmparser_message(This, "Line %u: Destination register %s not supported in PS 1\n",
1059 This->line_no,
1060 debug_print_dstreg(dst));
1061 set_parse_status(&This->status, PARSE_ERR);
1063 reg = map_oldps_register(dst, TRUE);
1064 instr->dst = reg;
1065 instr->has_dst = TRUE;
1068 static void asmparser_dstreg_ps_2(struct asm_parser *This,
1069 struct instruction *instr,
1070 const struct shader_reg *dst) {
1071 struct shader_reg reg;
1073 if(!check_reg_type(dst, ps_2_0_reg_allowed)) {
1074 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.0\n",
1075 This->line_no,
1076 debug_print_dstreg(dst));
1077 set_parse_status(&This->status, PARSE_ERR);
1079 check_shift_dstmod(This, instr->shift);
1080 reg = map_oldps_register(dst, TRUE);
1081 instr->dst = reg;
1082 instr->has_dst = TRUE;
1085 static void asmparser_dstreg_ps_2_x(struct asm_parser *This,
1086 struct instruction *instr,
1087 const struct shader_reg *dst) {
1088 struct shader_reg reg;
1090 if(!check_reg_type(dst, ps_2_x_reg_allowed)) {
1091 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.x\n",
1092 This->line_no,
1093 debug_print_dstreg(dst));
1094 set_parse_status(&This->status, PARSE_ERR);
1096 check_shift_dstmod(This, instr->shift);
1097 reg = map_oldps_register(dst, TRUE);
1098 instr->dst = reg;
1099 instr->has_dst = TRUE;
1102 static void asmparser_dstreg_ps_3(struct asm_parser *This,
1103 struct instruction *instr,
1104 const struct shader_reg *dst) {
1105 if(!check_reg_type(dst, ps_3_reg_allowed)) {
1106 asmparser_message(This, "Line %u: Destination register %s not supported in PS 3.0\n",
1107 This->line_no,
1108 debug_print_dstreg(dst));
1109 set_parse_status(&This->status, PARSE_ERR);
1111 check_shift_dstmod(This, instr->shift);
1112 instr->dst = *dst;
1113 instr->has_dst = TRUE;
1116 static void asmparser_predicate_supported(struct asm_parser *This,
1117 const struct shader_reg *predicate) {
1118 /* this sets the predicate of the last instruction added to the shader */
1119 if(!This->shader) return;
1120 if(This->shader->num_instrs == 0) ERR("Predicate without an instruction\n");
1121 This->shader->instr[This->shader->num_instrs - 1]->has_predicate = TRUE;
1122 This->shader->instr[This->shader->num_instrs - 1]->predicate = *predicate;
1125 static void asmparser_predicate_unsupported(struct asm_parser *This,
1126 const struct shader_reg *predicate) {
1127 asmparser_message(This, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This->line_no);
1128 set_parse_status(&This->status, PARSE_ERR);
1131 static void asmparser_coissue_supported(struct asm_parser *This) {
1132 /* this sets the coissue flag of the last instruction added to the shader */
1133 if(!This->shader) return;
1134 if(This->shader->num_instrs == 0){
1135 asmparser_message(This, "Line %u: Coissue flag on the first shader instruction\n", This->line_no);
1136 set_parse_status(&This->status, PARSE_ERR);
1138 This->shader->instr[This->shader->num_instrs-1]->coissue = TRUE;
1141 static void asmparser_coissue_unsupported(struct asm_parser *This) {
1142 asmparser_message(This, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This->line_no);
1143 set_parse_status(&This->status, PARSE_ERR);
1146 static const struct asmparser_backend parser_vs_1 = {
1147 asmparser_constF,
1148 asmparser_constI,
1149 asmparser_constB,
1151 asmparser_dstreg_vs_1,
1152 asmparser_srcreg_vs_1,
1154 asmparser_predicate_unsupported,
1155 asmparser_coissue_unsupported,
1157 asmparser_dcl_output_unsupported,
1158 asmparser_dcl_input,
1159 asmparser_dcl_sampler_unsupported,
1161 asmparser_end,
1163 asmparser_instr,
1166 static const struct asmparser_backend parser_vs_2 = {
1167 asmparser_constF,
1168 asmparser_constI,
1169 asmparser_constB,
1171 asmparser_dstreg_vs_2,
1172 asmparser_srcreg_vs_2,
1174 asmparser_predicate_supported,
1175 asmparser_coissue_unsupported,
1177 asmparser_dcl_output_unsupported,
1178 asmparser_dcl_input,
1179 asmparser_dcl_sampler_unsupported,
1181 asmparser_end,
1183 asmparser_instr,
1186 static const struct asmparser_backend parser_vs_3 = {
1187 asmparser_constF,
1188 asmparser_constI,
1189 asmparser_constB,
1191 asmparser_dstreg_vs_3,
1192 asmparser_srcreg_vs_3,
1194 asmparser_predicate_supported,
1195 asmparser_coissue_unsupported,
1197 asmparser_dcl_output,
1198 asmparser_dcl_input,
1199 asmparser_dcl_sampler,
1201 asmparser_end,
1203 asmparser_instr,
1206 static const struct asmparser_backend parser_ps_1_0123 = {
1207 asmparser_constF,
1208 asmparser_constI,
1209 asmparser_constB,
1211 asmparser_dstreg_ps_1_0123,
1212 asmparser_srcreg_ps_1_0123,
1214 asmparser_predicate_unsupported,
1215 asmparser_coissue_supported,
1217 asmparser_dcl_output_unsupported,
1218 asmparser_dcl_input_unsupported,
1219 asmparser_dcl_sampler_unsupported,
1221 asmparser_end,
1223 asmparser_instr,
1226 static const struct asmparser_backend parser_ps_1_4 = {
1227 asmparser_constF,
1228 asmparser_constI,
1229 asmparser_constB,
1231 asmparser_dstreg_ps_1_4,
1232 asmparser_srcreg_ps_1_4,
1234 asmparser_predicate_unsupported,
1235 asmparser_coissue_supported,
1237 asmparser_dcl_output_unsupported,
1238 asmparser_dcl_input_unsupported,
1239 asmparser_dcl_sampler_unsupported,
1241 asmparser_end,
1243 asmparser_instr,
1246 static const struct asmparser_backend parser_ps_2 = {
1247 asmparser_constF,
1248 asmparser_constI,
1249 asmparser_constB,
1251 asmparser_dstreg_ps_2,
1252 asmparser_srcreg_ps_2,
1254 asmparser_predicate_unsupported,
1255 asmparser_coissue_unsupported,
1257 asmparser_dcl_output_unsupported,
1258 asmparser_dcl_input_ps_2,
1259 asmparser_dcl_sampler,
1261 asmparser_end,
1263 asmparser_instr,
1266 static const struct asmparser_backend parser_ps_2_x = {
1267 asmparser_constF,
1268 asmparser_constI,
1269 asmparser_constB,
1271 asmparser_dstreg_ps_2_x,
1272 asmparser_srcreg_ps_2_x,
1274 asmparser_predicate_supported,
1275 asmparser_coissue_unsupported,
1277 asmparser_dcl_output_unsupported,
1278 asmparser_dcl_input_ps_2,
1279 asmparser_dcl_sampler,
1281 asmparser_end,
1283 asmparser_instr,
1286 static const struct asmparser_backend parser_ps_3 = {
1287 asmparser_constF,
1288 asmparser_constI,
1289 asmparser_constB,
1291 asmparser_dstreg_ps_3,
1292 asmparser_srcreg_ps_3,
1294 asmparser_predicate_supported,
1295 asmparser_coissue_unsupported,
1297 asmparser_dcl_output_unsupported,
1298 asmparser_dcl_input,
1299 asmparser_dcl_sampler,
1301 asmparser_end,
1303 asmparser_instr,
1306 static void gen_oldvs_output(struct bwriter_shader *shader) {
1307 record_declaration(shader, BWRITERDECLUSAGE_POSITION, 0, 0, TRUE, OPOS_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1308 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, TRUE, OT0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1309 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, TRUE, OT1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1310 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, TRUE, OT2_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1311 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, TRUE, OT3_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1312 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, TRUE, OT4_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1313 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, TRUE, OT5_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1314 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, TRUE, OT6_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1315 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, TRUE, OT7_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1316 record_declaration(shader, BWRITERDECLUSAGE_FOG, 0, 0, TRUE, OFOG_REG, OFOG_WRITEMASK, TRUE);
1317 record_declaration(shader, BWRITERDECLUSAGE_PSIZE, 0, 0, TRUE, OPTS_REG, OPTS_WRITEMASK, TRUE);
1318 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, TRUE, OD0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1319 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1322 static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
1323 switch(texcoords) {
1324 case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1325 /* fall through */
1326 case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1327 /* fall through */
1328 case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1329 /* fall through */
1330 case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1331 /* fall through */
1332 case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1333 /* fall through */
1334 case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1335 /* fall through */
1336 case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1337 /* fall through */
1338 case 1: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, FALSE, T0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1340 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, FALSE, C0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1341 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1344 void create_vs10_parser(struct asm_parser *ret) {
1345 TRACE_(parsed_shader)("vs_1_0\n");
1347 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1348 if(!ret->shader) {
1349 ERR("Failed to allocate memory for the shader\n");
1350 set_parse_status(&ret->status, PARSE_ERR);
1351 return;
1354 ret->shader->type = ST_VERTEX;
1355 ret->shader->major_version = 1;
1356 ret->shader->minor_version = 0;
1357 ret->funcs = &parser_vs_1;
1358 gen_oldvs_output(ret->shader);
1361 void create_vs11_parser(struct asm_parser *ret) {
1362 TRACE_(parsed_shader)("vs_1_1\n");
1364 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1365 if(!ret->shader) {
1366 ERR("Failed to allocate memory for the shader\n");
1367 set_parse_status(&ret->status, PARSE_ERR);
1368 return;
1371 ret->shader->type = ST_VERTEX;
1372 ret->shader->major_version = 1;
1373 ret->shader->minor_version = 1;
1374 ret->funcs = &parser_vs_1;
1375 gen_oldvs_output(ret->shader);
1378 void create_vs20_parser(struct asm_parser *ret) {
1379 TRACE_(parsed_shader)("vs_2_0\n");
1381 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1382 if(!ret->shader) {
1383 ERR("Failed to allocate memory for the shader\n");
1384 set_parse_status(&ret->status, PARSE_ERR);
1385 return;
1388 ret->shader->type = ST_VERTEX;
1389 ret->shader->major_version = 2;
1390 ret->shader->minor_version = 0;
1391 ret->funcs = &parser_vs_2;
1392 gen_oldvs_output(ret->shader);
1395 void create_vs2x_parser(struct asm_parser *ret) {
1396 TRACE_(parsed_shader)("vs_2_x\n");
1398 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1399 if(!ret->shader) {
1400 ERR("Failed to allocate memory for the shader\n");
1401 set_parse_status(&ret->status, PARSE_ERR);
1402 return;
1405 ret->shader->type = ST_VERTEX;
1406 ret->shader->major_version = 2;
1407 ret->shader->minor_version = 1;
1408 ret->funcs = &parser_vs_2;
1409 gen_oldvs_output(ret->shader);
1412 void create_vs30_parser(struct asm_parser *ret) {
1413 TRACE_(parsed_shader)("vs_3_0\n");
1415 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1416 if(!ret->shader) {
1417 ERR("Failed to allocate memory for the shader\n");
1418 set_parse_status(&ret->status, PARSE_ERR);
1419 return;
1422 ret->shader->type = ST_VERTEX;
1423 ret->shader->major_version = 3;
1424 ret->shader->minor_version = 0;
1425 ret->funcs = &parser_vs_3;
1428 void create_ps10_parser(struct asm_parser *ret) {
1429 TRACE_(parsed_shader)("ps_1_0\n");
1431 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1432 if(!ret->shader) {
1433 ERR("Failed to allocate memory for the shader\n");
1434 set_parse_status(&ret->status, PARSE_ERR);
1435 return;
1438 ret->shader->type = ST_PIXEL;
1439 ret->shader->major_version = 1;
1440 ret->shader->minor_version = 0;
1441 ret->funcs = &parser_ps_1_0123;
1442 gen_oldps_input(ret->shader, 4);
1445 void create_ps11_parser(struct asm_parser *ret) {
1446 TRACE_(parsed_shader)("ps_1_1\n");
1448 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1449 if(!ret->shader) {
1450 ERR("Failed to allocate memory for the shader\n");
1451 set_parse_status(&ret->status, PARSE_ERR);
1452 return;
1455 ret->shader->type = ST_PIXEL;
1456 ret->shader->major_version = 1;
1457 ret->shader->minor_version = 1;
1458 ret->funcs = &parser_ps_1_0123;
1459 gen_oldps_input(ret->shader, 4);
1462 void create_ps12_parser(struct asm_parser *ret) {
1463 TRACE_(parsed_shader)("ps_1_2\n");
1465 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1466 if(!ret->shader) {
1467 ERR("Failed to allocate memory for the shader\n");
1468 set_parse_status(&ret->status, PARSE_ERR);
1469 return;
1472 ret->shader->type = ST_PIXEL;
1473 ret->shader->major_version = 1;
1474 ret->shader->minor_version = 2;
1475 ret->funcs = &parser_ps_1_0123;
1476 gen_oldps_input(ret->shader, 4);
1479 void create_ps13_parser(struct asm_parser *ret) {
1480 TRACE_(parsed_shader)("ps_1_3\n");
1482 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1483 if(!ret->shader) {
1484 ERR("Failed to allocate memory for the shader\n");
1485 set_parse_status(&ret->status, PARSE_ERR);
1486 return;
1489 ret->shader->type = ST_PIXEL;
1490 ret->shader->major_version = 1;
1491 ret->shader->minor_version = 3;
1492 ret->funcs = &parser_ps_1_0123;
1493 gen_oldps_input(ret->shader, 4);
1496 void create_ps14_parser(struct asm_parser *ret) {
1497 TRACE_(parsed_shader)("ps_1_4\n");
1499 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1500 if(!ret->shader) {
1501 ERR("Failed to allocate memory for the shader\n");
1502 set_parse_status(&ret->status, PARSE_ERR);
1503 return;
1506 ret->shader->type = ST_PIXEL;
1507 ret->shader->major_version = 1;
1508 ret->shader->minor_version = 4;
1509 ret->funcs = &parser_ps_1_4;
1510 gen_oldps_input(ret->shader, 6);
1513 void create_ps20_parser(struct asm_parser *ret) {
1514 TRACE_(parsed_shader)("ps_2_0\n");
1516 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1517 if(!ret->shader) {
1518 ERR("Failed to allocate memory for the shader\n");
1519 set_parse_status(&ret->status, PARSE_ERR);
1520 return;
1523 ret->shader->type = ST_PIXEL;
1524 ret->shader->major_version = 2;
1525 ret->shader->minor_version = 0;
1526 ret->funcs = &parser_ps_2;
1527 gen_oldps_input(ret->shader, 8);
1530 void create_ps2x_parser(struct asm_parser *ret) {
1531 TRACE_(parsed_shader)("ps_2_x\n");
1533 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1534 if(!ret->shader) {
1535 ERR("Failed to allocate memory for the shader\n");
1536 set_parse_status(&ret->status, PARSE_ERR);
1537 return;
1540 ret->shader->type = ST_PIXEL;
1541 ret->shader->major_version = 2;
1542 ret->shader->minor_version = 1;
1543 ret->funcs = &parser_ps_2_x;
1544 gen_oldps_input(ret->shader, 8);
1547 void create_ps30_parser(struct asm_parser *ret) {
1548 TRACE_(parsed_shader)("ps_3_0\n");
1550 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1551 if(!ret->shader) {
1552 ERR("Failed to allocate memory for the shader\n");
1553 set_parse_status(&ret->status, PARSE_ERR);
1554 return;
1557 ret->shader->type = ST_PIXEL;
1558 ret->shader->major_version = 3;
1559 ret->shader->minor_version = 0;
1560 ret->funcs = &parser_ps_3;