msvcrt: Added _wassert implementation.
[wine] / dlls / d3dcompiler_43 / asmparser.c
CommitLineData
95afbead
MB
1/*
2 * Direct3D asm shader parser
3 *
4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2009 Matteo Bruni
6 *
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.
11 *
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.
16 *
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
20 *
21 */
22
23#include "config.h"
24#include "wine/port.h"
25#include "wine/debug.h"
26
5dcb2e4b 27#include "d3dcompiler_private.h"
95afbead
MB
28
29WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
30WINE_DECLARE_DEBUG_CHANNEL(parsed_shader);
31
32
5050f7c8
MB
33/* How to map vs 1.0 and 2.0 varyings to 3.0 ones
34 * oTx is mapped to ox, which happens to be an
35 * identical mapping since BWRITERSPR_TEXCRDOUT == BWRITERSPR_OUTPUT
36 * oPos, oFog and point size are mapped to general output regs as well.
37 * the vs 1.x and 2.x parser functions add varying declarations
38 * to the shader, and the 1.x and 2.x output functions check those varyings
39 */
40#define OT0_REG 0
41#define OT1_REG 1
42#define OT2_REG 2
43#define OT3_REG 3
44#define OT4_REG 4
45#define OT5_REG 5
46#define OT6_REG 6
47#define OT7_REG 7
48#define OPOS_REG 8
49#define OFOG_REG 9
50#define OFOG_WRITEMASK BWRITERSP_WRITEMASK_0
51#define OPTS_REG 9
52#define OPTS_WRITEMASK BWRITERSP_WRITEMASK_1
53#define OD0_REG 10
54#define OD1_REG 11
55
5786d3a0
MB
56/* Input color registers 0-1 are identically mapped */
57#define C0_VARYING 0
58#define C1_VARYING 1
59#define T0_VARYING 2
60#define T1_VARYING 3
61#define T2_VARYING 4
62#define T3_VARYING 5
63#define T4_VARYING 6
64#define T5_VARYING 7
65#define T6_VARYING 8
66#define T7_VARYING 9
5050f7c8 67
95afbead
MB
68/****************************************************************
69 * Common(non-version specific) shader parser control code *
70 ****************************************************************/
71
72static void asmparser_end(struct asm_parser *This) {
73 TRACE("Finalizing shader\n");
74}
75
dc1fa014
MB
76static void asmparser_constF(struct asm_parser *This, DWORD reg, float x, float y, float z, float w) {
77 if(!This->shader) return;
78 TRACE("Adding float constant %u at pos %u\n", reg, This->shader->num_cf);
79 TRACE_(parsed_shader)("def c%u, %f, %f, %f, %f\n", reg, x, y, z, w);
80 if(!add_constF(This->shader, reg, x, y, z, w)) {
81 ERR("Out of memory\n");
82 set_parse_status(This, PARSE_ERR);
83 }
84}
85
1371e71f
MB
86static void asmparser_constB(struct asm_parser *This, DWORD reg, BOOL x) {
87 if(!This->shader) return;
88 TRACE("Adding boolean constant %u at pos %u\n", reg, This->shader->num_cb);
89 TRACE_(parsed_shader)("def b%u, %s\n", reg, x ? "true" : "false");
90 if(!add_constB(This->shader, reg, x)) {
91 ERR("Out of memory\n");
92 set_parse_status(This, PARSE_ERR);
93 }
94}
95
fa44f242
MB
96static void asmparser_constI(struct asm_parser *This, DWORD reg, INT x, INT y, INT z, INT w) {
97 if(!This->shader) return;
98 TRACE("Adding integer constant %u at pos %u\n", reg, This->shader->num_ci);
99 TRACE_(parsed_shader)("def i%u, %d, %d, %d, %d\n", reg, x, y, z, w);
100 if(!add_constI(This->shader, reg, x, y, z, w)) {
101 ERR("Out of memory\n");
102 set_parse_status(This, PARSE_ERR);
103 }
104}
105
b627d13e
MB
106static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num,
107 const struct shader_reg *reg) {
108 if(!This->shader) return;
109 if(This->shader->type == ST_PIXEL) {
110 asmparser_message(This, "Line %u: Output register declared in a pixel shader\n", This->line_no);
111 set_parse_status(This, PARSE_ERR);
112 }
aaf78f1a 113 if(!record_declaration(This->shader, usage, num, 0, TRUE, reg->regnum, reg->u.writemask, FALSE)) {
b627d13e
MB
114 ERR("Out of memory\n");
115 set_parse_status(This, PARSE_ERR);
116 }
117}
118
0ea6f795
MB
119static void asmparser_dcl_output_unsupported(struct asm_parser *This, DWORD usage, DWORD num,
120 const struct shader_reg *reg) {
121 asmparser_message(This, "Line %u: Output declaration unsupported in this shader version\n", This->line_no);
122 set_parse_status(This, PARSE_ERR);
123}
124
6cbd5114 125static void asmparser_dcl_input(struct asm_parser *This, DWORD usage, DWORD num,
7de630ef 126 DWORD mod, const struct shader_reg *reg) {
a74978df
MB
127 struct instruction instr;
128
6cbd5114 129 if(!This->shader) return;
7de630ef
MB
130 if(mod != 0 &&
131 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
132 (mod != BWRITERSPDM_MSAMPCENTROID &&
133 mod != BWRITERSPDM_PARTIALPRECISION))) {
134 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
135 set_parse_status(This, PARSE_ERR);
136 return;
137 }
a74978df
MB
138
139 /* Check register type and modifiers */
140 instr.dstmod = mod;
141 instr.shift = 0;
142 This->funcs->dstreg(This, &instr, reg);
143
aaf78f1a 144 if(!record_declaration(This->shader, usage, num, mod, FALSE, reg->regnum, reg->u.writemask, FALSE)) {
6cbd5114
MB
145 ERR("Out of memory\n");
146 set_parse_status(This, PARSE_ERR);
147 }
148}
149
00951f84
MB
150static void asmparser_dcl_input_ps_2(struct asm_parser *This, DWORD usage, DWORD num,
151 DWORD mod, const struct shader_reg *reg) {
152 struct instruction instr;
153
154 if(!This->shader) return;
00951f84
MB
155 instr.dstmod = mod;
156 instr.shift = 0;
157 This->funcs->dstreg(This, &instr, reg);
aaf78f1a 158 if(!record_declaration(This->shader, usage, num, mod, FALSE, instr.dst.regnum, instr.dst.u.writemask, FALSE)) {
00951f84
MB
159 ERR("Out of memory\n");
160 set_parse_status(This, PARSE_ERR);
161 }
162}
163
ac8f8c02
HV
164static void asmparser_dcl_input_unsupported(struct asm_parser *This,
165 DWORD usage, DWORD num, DWORD mod, const struct shader_reg *reg)
166{
bfa39992
MB
167 asmparser_message(This, "Line %u: Input declaration unsupported in this shader version\n", This->line_no);
168 set_parse_status(This, PARSE_ERR);
169}
170
25d4fe68
MB
171static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype,
172 DWORD mod, DWORD regnum,
173 unsigned int line_no) {
745b5fe8 174 if(!This->shader) return;
25d4fe68
MB
175 if(mod != 0 &&
176 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
177 (mod != BWRITERSPDM_MSAMPCENTROID &&
178 mod != BWRITERSPDM_PARTIALPRECISION))) {
179 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
180 set_parse_status(This, PARSE_ERR);
181 return;
182 }
183 if(!record_sampler(This->shader, samptype, mod, regnum)) {
745b5fe8
MB
184 ERR("Out of memory\n");
185 set_parse_status(This, PARSE_ERR);
186 }
187}
188
ac8f8c02
HV
189static void asmparser_dcl_sampler_unsupported(struct asm_parser *This,
190 DWORD samptype, DWORD mod, DWORD regnum, unsigned int line_no)
191{
5a5844d4
MB
192 asmparser_message(This, "Line %u: Sampler declaration unsupported in this shader version\n", This->line_no);
193 set_parse_status(This, PARSE_ERR);
194}
195
5050f7c8
MB
196static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift,
197 const struct shader_reg *dst,
198 const struct src_regs *srcs) {
199 struct instruction *instr;
200
201 if(!srcs || srcs->count != 3) {
202 asmparser_message(This, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This->line_no);
203 set_parse_status(This, PARSE_ERR);
204 return;
205 }
206
207 instr = alloc_instr(3);
208 if(!instr) {
209 ERR("Error allocating memory for the instruction\n");
210 set_parse_status(This, PARSE_ERR);
211 return;
212 }
213
214 instr->opcode = BWRITERSIO_SINCOS;
215 instr->dstmod = mod;
216 instr->shift = shift;
217 instr->comptype = 0;
218
219 This->funcs->dstreg(This, instr, dst);
220 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
221 This->funcs->srcreg(This, instr, 1, &srcs->reg[1]);
222 This->funcs->srcreg(This, instr, 2, &srcs->reg[2]);
223
224 if(!add_instruction(This->shader, instr)) {
225 ERR("Out of memory\n");
226 set_parse_status(This, PARSE_ERR);
227 }
228}
229
d567a030
MB
230static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) {
231 struct shader_reg ret;
232 switch(reg->type) {
233 case BWRITERSPR_TEXTURE:
234 if(tex_varying) {
235 ret = *reg;
236 ret.type = BWRITERSPR_INPUT;
237 switch(reg->regnum) {
238 case 0: ret.regnum = T0_VARYING; break;
239 case 1: ret.regnum = T1_VARYING; break;
240 case 2: ret.regnum = T2_VARYING; break;
241 case 3: ret.regnum = T3_VARYING; break;
242 case 4: ret.regnum = T4_VARYING; break;
243 case 5: ret.regnum = T5_VARYING; break;
244 case 6: ret.regnum = T6_VARYING; break;
245 case 7: ret.regnum = T7_VARYING; break;
246 default:
247 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
248 return *reg;
249 }
250 return ret;
251 } else {
252 ret = *reg;
253 ret.type = BWRITERSPR_TEMP;
254 switch(reg->regnum) {
255 case 0: ret.regnum = T0_REG; break;
256 case 1: ret.regnum = T1_REG; break;
257 case 2: ret.regnum = T2_REG; break;
258 case 3: ret.regnum = T3_REG; break;
259 default:
260 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
261 return *reg;
262 }
263 return ret;
264 }
265
266 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
267 to 3.0 ones */
268
269 default: return *reg;
270 }
271}
272
273static void asmparser_texcoord(struct asm_parser *This, DWORD mod, DWORD shift,
274 const struct shader_reg *dst,
275 const struct src_regs *srcs) {
276 struct instruction *instr;
277
278 if(srcs) {
279 asmparser_message(This, "Line %u: Source registers in texcoord instruction\n", This->line_no);
280 set_parse_status(This, PARSE_ERR);
281 return;
282 }
283
284 instr = alloc_instr(1);
285 if(!instr) {
286 ERR("Error allocating memory for the instruction\n");
287 set_parse_status(This, PARSE_ERR);
288 return;
289 }
290
291 /* texcoord copies the texture coord data into a temporary register-like
292 * readable form. In newer shader models this equals a MOV from v0 to r0,
293 * record it as this.
294 */
295 instr->opcode = BWRITERSIO_MOV;
296 instr->dstmod = mod | BWRITERSPDM_SATURATE; /* texcoord clamps to [0;1] */
297 instr->shift = shift;
298 instr->comptype = 0;
299
300 This->funcs->dstreg(This, instr, dst);
301 /* The src reg needs special care */
302 instr->src[0] = map_oldps_register(dst, TRUE);
303
304 if(!add_instruction(This->shader, instr)) {
305 ERR("Out of memory\n");
306 set_parse_status(This, PARSE_ERR);
307 }
308}
309
bfa39992
MB
310static void asmparser_texcrd(struct asm_parser *This, DWORD mod, DWORD shift,
311 const struct shader_reg *dst,
312 const struct src_regs *srcs) {
313 struct instruction *instr;
314
315 if(!srcs || srcs->count != 1) {
316 asmparser_message(This, "Line %u: Wrong number of source registers in texcrd instruction\n", This->line_no);
317 set_parse_status(This, PARSE_ERR);
318 return;
319 }
320
321 instr = alloc_instr(1);
322 if(!instr) {
323 ERR("Error allocating memory for the instruction\n");
324 set_parse_status(This, PARSE_ERR);
325 return;
326 }
327
328 /* The job of texcrd is done by mov in later shader versions */
329 instr->opcode = BWRITERSIO_MOV;
330 instr->dstmod = mod;
331 instr->shift = shift;
332 instr->comptype = 0;
333
334 This->funcs->dstreg(This, instr, dst);
335 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
336
337 if(!add_instruction(This->shader, instr)) {
338 ERR("Out of memory\n");
339 set_parse_status(This, PARSE_ERR);
340 }
341}
342
d567a030
MB
343static void asmparser_texkill(struct asm_parser *This,
344 const struct shader_reg *dst) {
345 struct instruction *instr = alloc_instr(0);
346
347 if(!instr) {
348 ERR("Error allocating memory for the instruction\n");
349 set_parse_status(This, PARSE_ERR);
350 return;
351 }
352
353 instr->opcode = BWRITERSIO_TEXKILL;
354 instr->dstmod = 0;
355 instr->shift = 0;
356 instr->comptype = 0;
357
358 /* Do not run the dst register through the normal
359 * register conversion. If used with ps_1_0 to ps_1_3
360 * the texture coordinate from that register is used,
361 * not the temporary register value. In ps_1_4 and
362 * ps_2_0 t0 is always a varying and temporaries can
363 * be used with texkill.
364 */
365 instr->dst = map_oldps_register(dst, TRUE);
366 instr->has_dst = TRUE;
367
368 if(!add_instruction(This->shader, instr)) {
369 ERR("Out of memory\n");
370 set_parse_status(This, PARSE_ERR);
371 }
372}
373
374static void asmparser_texhelper(struct asm_parser *This, DWORD mod, DWORD shift,
375 const struct shader_reg *dst,
376 const struct shader_reg *src0) {
377 struct instruction *instr = alloc_instr(2);
378
379 if(!instr) {
380 ERR("Error allocating memory for the instruction\n");
381 set_parse_status(This, PARSE_ERR);
382 return;
383 }
384
385 instr->opcode = BWRITERSIO_TEX;
386 instr->dstmod = mod;
387 instr->shift = shift;
388 instr->comptype = 0;
389 /* The dest register can be mapped normally to a temporary register */
390 This->funcs->dstreg(This, instr, dst);
391 /* Use the src passed as parameter by the specific instruction handler */
392 instr->src[0] = *src0;
393
394 /* The 2nd source register is the sampler register with the
395 * destination's regnum
396 */
397 ZeroMemory(&instr->src[1], sizeof(instr->src[1]));
398 instr->src[1].type = BWRITERSPR_SAMPLER;
399 instr->src[1].regnum = dst->regnum;
aaf78f1a 400 instr->src[1].u.swizzle = BWRITERVS_NOSWIZZLE;
d567a030
MB
401 instr->src[1].srcmod = BWRITERSPSM_NONE;
402 instr->src[1].rel_reg = NULL;
403
404 if(!add_instruction(This->shader, instr)) {
405 ERR("Out of memory\n");
406 set_parse_status(This, PARSE_ERR);
407 }
408}
409
410static void asmparser_tex(struct asm_parser *This, DWORD mod, DWORD shift,
411 const struct shader_reg *dst) {
412 struct shader_reg src;
413
414 /* The first source register is the varying containing the coordinate */
415 src = map_oldps_register(dst, TRUE);
416 asmparser_texhelper(This, mod, shift, dst, &src);
417}
418
bfa39992
MB
419static void asmparser_texld14(struct asm_parser *This, DWORD mod, DWORD shift,
420 const struct shader_reg *dst,
421 const struct src_regs *srcs) {
422 struct instruction *instr;
423
424 if(!srcs || srcs->count != 1) {
425 asmparser_message(This, "Line %u: texld (PS 1.4) has a wrong number of source registers\n", This->line_no);
426 set_parse_status(This, PARSE_ERR);
427 return;
428 }
429
430 instr = alloc_instr(2);
431 if(!instr) {
432 ERR("Error allocating memory for the instruction\n");
433 set_parse_status(This, PARSE_ERR);
434 return;
435 }
436
437 /* This code is recording a texld instruction, not tex. However,
438 * texld borrows the opcode of tex
439 */
440 instr->opcode = BWRITERSIO_TEX;
441 instr->dstmod = mod;
442 instr->shift = shift;
443 instr->comptype = 0;
444
445 This->funcs->dstreg(This, instr, dst);
446 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
447
448 /* The 2nd source register is the sampler register with the
449 * destination's regnum
450 */
451 ZeroMemory(&instr->src[1], sizeof(instr->src[1]));
452 instr->src[1].type = BWRITERSPR_SAMPLER;
453 instr->src[1].regnum = dst->regnum;
aaf78f1a 454 instr->src[1].u.swizzle = BWRITERVS_NOSWIZZLE;
bfa39992
MB
455 instr->src[1].srcmod = BWRITERSPSM_NONE;
456 instr->src[1].rel_reg = NULL;
457
458 if(!add_instruction(This->shader, instr)) {
459 ERR("Out of memory\n");
460 set_parse_status(This, PARSE_ERR);
461 }
462}
463
d567a030
MB
464static void asmparser_texreg2ar(struct asm_parser *This, DWORD mod, DWORD shift,
465 const struct shader_reg *dst,
466 const struct shader_reg *src0) {
467 struct shader_reg src;
468
469 src = map_oldps_register(src0, FALSE);
470 /* Supply the correct swizzle */
aaf78f1a 471 src.u.swizzle = BWRITERVS_X_W | BWRITERVS_Y_X | BWRITERVS_Z_X | BWRITERVS_W_X;
d567a030
MB
472 asmparser_texhelper(This, mod, shift, dst, &src);
473}
474
475static void asmparser_texreg2gb(struct asm_parser *This, DWORD mod, DWORD shift,
476 const struct shader_reg *dst,
477 const struct shader_reg *src0) {
478 struct shader_reg src;
479
480 src = map_oldps_register(src0, FALSE);
481 /* Supply the correct swizzle */
aaf78f1a 482 src.u.swizzle = BWRITERVS_X_Y | BWRITERVS_Y_Z | BWRITERVS_Z_Z | BWRITERVS_W_Z;
d567a030
MB
483 asmparser_texhelper(This, mod, shift, dst, &src);
484}
485
486static void asmparser_texreg2rgb(struct asm_parser *This, DWORD mod, DWORD shift,
487 const struct shader_reg *dst,
488 const struct shader_reg *src0) {
489 struct shader_reg src;
490
491 src = map_oldps_register(src0, FALSE);
492 /* Supply the correct swizzle */
aaf78f1a 493 src.u.swizzle = BWRITERVS_X_X | BWRITERVS_Y_Y | BWRITERVS_Z_Z | BWRITERVS_W_Z;
d567a030
MB
494 asmparser_texhelper(This, mod, shift, dst, &src);
495}
496
497/* Complex pixel shader 1.3 instructions like texm3x3tex are tricky - the
498 * bytecode writer works instruction by instruction, so we can't properly
499 * convert these from/to equivalent ps_3_0 instructions. Then simply keep using
500 * the ps_1_3 opcodes and just adapt the registers in the common fashion (i.e.
501 * go through asmparser_instr).
502 */
503
95afbead
MB
504static void asmparser_instr(struct asm_parser *This, DWORD opcode,
505 DWORD mod, DWORD shift,
506 BWRITER_COMPARISON_TYPE comp,
507 const struct shader_reg *dst,
508 const struct src_regs *srcs, int expectednsrcs) {
509 struct instruction *instr;
510 unsigned int i;
511 BOOL firstreg = TRUE;
512 unsigned int src_count = srcs ? srcs->count : 0;
513
514 if(!This->shader) return;
515
949eca40 516 TRACE_(parsed_shader)("%s%s%s%s ", debug_print_opcode(opcode),
93b2648c 517 debug_print_dstmod(mod),
949eca40 518 debug_print_shift(shift),
93b2648c 519 debug_print_comp(comp));
95afbead 520 if(dst) {
a5e55c15 521 TRACE_(parsed_shader)("%s", debug_print_dstreg(dst));
95afbead
MB
522 firstreg = FALSE;
523 }
524 for(i = 0; i < src_count; i++) {
525 if(!firstreg) TRACE_(parsed_shader)(", ");
526 else firstreg = FALSE;
a5e55c15 527 TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i]));
95afbead
MB
528 }
529 TRACE_(parsed_shader)("\n");
530
5050f7c8
MB
531 /* Check for instructions with different syntaxes in different shader versio
532ns */
533 switch(opcode) {
534 case BWRITERSIO_SINCOS:
535 /* The syntax changes between vs 2 and the other shader versions */
536 if(This->shader->version == BWRITERVS_VERSION(2, 0) ||
537 This->shader->version == BWRITERVS_VERSION(2, 1)) {
538 asmparser_sincos(This, mod, shift, dst, srcs);
539 return;
540 }
541 /* Use the default handling */
ac8f8c02 542 break;
bfa39992
MB
543 case BWRITERSIO_TEXCOORD:
544 /* texcoord/texcrd are two instructions present only in PS <= 1.3 and PS 1.4 respectively */
d567a030
MB
545 if(This->shader->version == BWRITERPS_VERSION(1, 4))
546 asmparser_texcrd(This, mod, shift, dst, srcs);
547 else asmparser_texcoord(This, mod, shift, dst, srcs);
bfa39992
MB
548 return;
549 case BWRITERSIO_TEX:
550 /* this encodes both the tex PS 1.x instruction and the
551 texld 1.4/2.0+ instruction */
d567a030
MB
552 if(This->shader->version == BWRITERPS_VERSION(1, 1) ||
553 This->shader->version == BWRITERPS_VERSION(1, 2) ||
554 This->shader->version == BWRITERPS_VERSION(1, 3)) {
555 asmparser_tex(This, mod, shift, dst);
556 return;
557 }
558 else if(This->shader->version == BWRITERPS_VERSION(1, 4)) {
bfa39992
MB
559 asmparser_texld14(This, mod, shift, dst, srcs);
560 return;
561 }
562 /* else fallback to the standard behavior */
5050f7c8
MB
563 break;
564 }
565
95afbead
MB
566 if(src_count != expectednsrcs) {
567 asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no);
568 set_parse_status(This, PARSE_ERR);
569 return;
570 }
571
d567a030
MB
572 /* Handle PS 1.x instructions, "regularizing" them */
573 switch(opcode) {
574 case BWRITERSIO_TEXKILL:
575 asmparser_texkill(This, dst);
576 return;
577 case BWRITERSIO_TEXREG2AR:
578 asmparser_texreg2ar(This, mod, shift, dst, &srcs->reg[0]);
579 return;
580 case BWRITERSIO_TEXREG2GB:
581 asmparser_texreg2gb(This, mod, shift, dst, &srcs->reg[0]);
582 return;
583 case BWRITERSIO_TEXREG2RGB:
584 asmparser_texreg2rgb(This, mod, shift, dst, &srcs->reg[0]);
585 return;
586 }
587
95afbead
MB
588 instr = alloc_instr(src_count);
589 if(!instr) {
590 ERR("Error allocating memory for the instruction\n");
591 set_parse_status(This, PARSE_ERR);
592 return;
593 }
594
595 instr->opcode = opcode;
596 instr->dstmod = mod;
597 instr->shift = shift;
598 instr->comptype = comp;
599 if(dst) This->funcs->dstreg(This, instr, dst);
600 for(i = 0; i < src_count; i++) {
601 This->funcs->srcreg(This, instr, i, &srcs->reg[i]);
602 }
603
604 if(!add_instruction(This->shader, instr)) {
605 ERR("Out of memory\n");
606 set_parse_status(This, PARSE_ERR);
607 }
608}
609
5050f7c8
MB
610static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
611 struct shader_reg ret;
612 switch(reg->type) {
613 case BWRITERSPR_RASTOUT:
614 ret = *reg;
615 ret.type = BWRITERSPR_OUTPUT;
616 switch(reg->regnum) {
617 case BWRITERSRO_POSITION:
618 ret.regnum = OPOS_REG;
619 break;
620 case BWRITERSRO_FOG:
621 ret.regnum = OFOG_REG;
aaf78f1a 622 ret.u.writemask = OFOG_WRITEMASK;
5050f7c8
MB
623 break;
624 case BWRITERSRO_POINT_SIZE:
625 ret.regnum = OPTS_REG;
aaf78f1a 626 ret.u.writemask = OPTS_WRITEMASK;
5050f7c8
MB
627 break;
628 default:
629 FIXME("Unhandled RASTOUT register %u\n", reg->regnum);
630 return *reg;
631 }
632 return ret;
633
634 case BWRITERSPR_TEXCRDOUT:
635 ret = *reg;
636 ret.type = BWRITERSPR_OUTPUT;
637 switch(reg->regnum) {
638 case 0: ret.regnum = OT0_REG; break;
639 case 1: ret.regnum = OT1_REG; break;
640 case 2: ret.regnum = OT2_REG; break;
641 case 3: ret.regnum = OT3_REG; break;
642 case 4: ret.regnum = OT4_REG; break;
643 case 5: ret.regnum = OT5_REG; break;
644 case 6: ret.regnum = OT6_REG; break;
645 case 7: ret.regnum = OT7_REG; break;
646 default:
647 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum);
648 return *reg;
649 }
650 return ret;
651
652 case BWRITERSPR_ATTROUT:
653 ret = *reg;
654 ret.type = BWRITERSPR_OUTPUT;
655 switch(reg->regnum) {
656 case 0: ret.regnum = OD0_REG; break;
657 case 1: ret.regnum = OD1_REG; break;
658 default:
659 FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum);
660 return *reg;
661 }
662 return ret;
663
664 default: return *reg;
665 }
666}
667
c1f7faca
MB
668/* Checks for unsupported source modifiers in VS (all versions) or
669 PS 2.0 and newer */
670static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) {
671 if(srcmod == BWRITERSPSM_BIAS || srcmod == BWRITERSPSM_BIASNEG ||
672 srcmod == BWRITERSPSM_SIGN || srcmod == BWRITERSPSM_SIGNNEG ||
673 srcmod == BWRITERSPSM_COMP || srcmod == BWRITERSPSM_X2 ||
674 srcmod == BWRITERSPSM_X2NEG || srcmod == BWRITERSPSM_DZ ||
675 srcmod == BWRITERSPSM_DW) {
676 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
677 This->line_no,
678 debug_print_srcmod(srcmod));
679 set_parse_status(This, PARSE_ERR);
680 }
681}
682
5050f7c8
MB
683static void check_abs_srcmod(struct asm_parser *This, DWORD srcmod) {
684 if(srcmod == BWRITERSPSM_ABS || srcmod == BWRITERSPSM_ABSNEG) {
685 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
686 This->line_no,
687 debug_print_srcmod(srcmod));
688 set_parse_status(This, PARSE_ERR);
689 }
690}
691
c1f7faca
MB
692static void check_loop_swizzle(struct asm_parser *This,
693 const struct shader_reg *src) {
aaf78f1a 694 if((src->type == BWRITERSPR_LOOP && src->u.swizzle != BWRITERVS_NOSWIZZLE) ||
c1f7faca 695 (src->rel_reg && src->rel_reg->type == BWRITERSPR_LOOP &&
aaf78f1a 696 src->rel_reg->u.swizzle != BWRITERVS_NOSWIZZLE)) {
c1f7faca
MB
697 asmparser_message(This, "Line %u: Swizzle not allowed on aL register\n", This->line_no);
698 set_parse_status(This, PARSE_ERR);
699 }
700}
701
702static void check_shift_dstmod(struct asm_parser *This, DWORD shift) {
703 if(shift != 0) {
704 asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n",
705 This->line_no);
706 set_parse_status(This, PARSE_ERR);
707 }
708}
709
710static void check_ps_dstmod(struct asm_parser *This, DWORD dstmod) {
711 if(dstmod == BWRITERSPDM_PARTIALPRECISION ||
712 dstmod == BWRITERSPDM_MSAMPCENTROID) {
713 asmparser_message(This, "Line %u: Instruction modifier %s not supported in this shader version\n",
714 This->line_no,
715 debug_print_dstmod(dstmod));
716 set_parse_status(This, PARSE_ERR);
717 }
718}
719
720struct allowed_reg_type {
721 DWORD type;
722 DWORD count;
084d5f1f 723 BOOL reladdr;
c1f7faca
MB
724};
725
726static BOOL check_reg_type(const struct shader_reg *reg,
727 const struct allowed_reg_type *allowed) {
728 unsigned int i = 0;
729
730 while(allowed[i].type != ~0U) {
731 if(reg->type == allowed[i].type) {
084d5f1f
MB
732 if(reg->rel_reg) {
733 if(allowed[i].reladdr)
734 return TRUE; /* The relative addressing register
735 can have a negative value, we
736 can't check the register index */
737 return FALSE;
738 }
c1f7faca
MB
739 if(reg->regnum < allowed[i].count) return TRUE;
740 return FALSE;
741 }
742 i++;
743 }
744 return FALSE;
745}
746
747/* Native assembler doesn't do separate checks for src and dst registers */
913278c5
MB
748static const struct allowed_reg_type vs_1_reg_allowed[] = {
749 { BWRITERSPR_TEMP, 12, FALSE },
750 { BWRITERSPR_INPUT, 16, FALSE },
751 { BWRITERSPR_CONST, ~0U, TRUE },
752 { BWRITERSPR_ADDR, 1, FALSE },
753 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
754 { BWRITERSPR_ATTROUT, 2, FALSE },
755 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
756 { ~0U, 0 } /* End tag */
757};
758
759/* struct instruction *asmparser_srcreg
760 *
761 * Records a source register in the instruction and does shader version
762 * specific checks and modifications on it
763 *
764 * Parameters:
765 * This: Shader parser instance
766 * instr: instruction to store the register in
767 * num: Number of source register
768 * src: Pointer to source the register structure. The caller can free
769 * it afterwards
770 */
771static void asmparser_srcreg_vs_1(struct asm_parser *This,
772 struct instruction *instr, int num,
773 const struct shader_reg *src) {
774 struct shader_reg reg;
775
776 if(!check_reg_type(src, vs_1_reg_allowed)) {
777 asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n",
778 This->line_no,
a5e55c15 779 debug_print_srcreg(src));
913278c5
MB
780 set_parse_status(This, PARSE_ERR);
781 }
782 check_legacy_srcmod(This, src->srcmod);
783 check_abs_srcmod(This, src->srcmod);
784 reg = map_oldvs_register(src);
785 memcpy(&instr->src[num], &reg, sizeof(reg));
786}
787
5050f7c8 788static const struct allowed_reg_type vs_2_reg_allowed[] = {
084d5f1f
MB
789 { BWRITERSPR_TEMP, 12, FALSE },
790 { BWRITERSPR_INPUT, 16, FALSE },
791 { BWRITERSPR_CONST, ~0U, TRUE },
792 { BWRITERSPR_ADDR, 1, FALSE },
793 { BWRITERSPR_CONSTBOOL, 16, FALSE },
794 { BWRITERSPR_CONSTINT, 16, FALSE },
795 { BWRITERSPR_LOOP, 1, FALSE },
796 { BWRITERSPR_LABEL, 2048, FALSE },
797 { BWRITERSPR_PREDICATE, 1, FALSE },
798 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
799 { BWRITERSPR_ATTROUT, 2, FALSE },
800 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
5050f7c8
MB
801 { ~0U, 0 } /* End tag */
802};
803
804static void asmparser_srcreg_vs_2(struct asm_parser *This,
805 struct instruction *instr, int num,
806 const struct shader_reg *src) {
807 struct shader_reg reg;
808
809 if(!check_reg_type(src, vs_2_reg_allowed)) {
810 asmparser_message(This, "Line %u: Source register %s not supported in VS 2\n",
811 This->line_no,
a5e55c15 812 debug_print_srcreg(src));
5050f7c8
MB
813 set_parse_status(This, PARSE_ERR);
814 }
815 check_loop_swizzle(This, src);
816 check_legacy_srcmod(This, src->srcmod);
817 check_abs_srcmod(This, src->srcmod);
818 reg = map_oldvs_register(src);
819 memcpy(&instr->src[num], &reg, sizeof(reg));
820}
821
c1f7faca 822static const struct allowed_reg_type vs_3_reg_allowed[] = {
084d5f1f
MB
823 { BWRITERSPR_TEMP, 32, FALSE },
824 { BWRITERSPR_INPUT, 16, TRUE },
825 { BWRITERSPR_CONST, ~0U, TRUE },
826 { BWRITERSPR_ADDR, 1, FALSE },
827 { BWRITERSPR_CONSTBOOL, 16, FALSE },
828 { BWRITERSPR_CONSTINT, 16, FALSE },
829 { BWRITERSPR_LOOP, 1, FALSE },
830 { BWRITERSPR_LABEL, 2048, FALSE },
831 { BWRITERSPR_PREDICATE, 1, FALSE },
832 { BWRITERSPR_SAMPLER, 4, FALSE },
833 { BWRITERSPR_OUTPUT, 12, TRUE },
c1f7faca
MB
834 { ~0U, 0 } /* End tag */
835};
836
95afbead
MB
837static void asmparser_srcreg_vs_3(struct asm_parser *This,
838 struct instruction *instr, int num,
839 const struct shader_reg *src) {
c1f7faca
MB
840 if(!check_reg_type(src, vs_3_reg_allowed)) {
841 asmparser_message(This, "Line %u: Source register %s not supported in VS 3.0\n",
842 This->line_no,
a5e55c15 843 debug_print_srcreg(src));
c1f7faca
MB
844 set_parse_status(This, PARSE_ERR);
845 }
846 check_loop_swizzle(This, src);
847 check_legacy_srcmod(This, src->srcmod);
95afbead
MB
848 memcpy(&instr->src[num], src, sizeof(*src));
849}
850
d567a030
MB
851static const struct allowed_reg_type ps_1_0123_reg_allowed[] = {
852 { BWRITERSPR_CONST, 8, FALSE },
853 { BWRITERSPR_TEMP, 2, FALSE },
854 { BWRITERSPR_TEXTURE, 4, FALSE },
855 { BWRITERSPR_INPUT, 2, FALSE },
856 { ~0U, 0 } /* End tag */
857};
858
859static void asmparser_srcreg_ps_1_0123(struct asm_parser *This,
860 struct instruction *instr, int num,
861 const struct shader_reg *src) {
862 struct shader_reg reg;
863
864 if(!check_reg_type(src, ps_1_0123_reg_allowed)) {
865 asmparser_message(This, "Line %u: Source register %s not supported in <== PS 1.3\n",
866 This->line_no,
867 debug_print_srcreg(src));
868 set_parse_status(This, PARSE_ERR);
869 }
870 check_abs_srcmod(This, src->srcmod);
871 reg = map_oldps_register(src, FALSE);
872 memcpy(&instr->src[num], &reg, sizeof(reg));
873}
874
bfa39992
MB
875static const struct allowed_reg_type ps_1_4_reg_allowed[] = {
876 { BWRITERSPR_CONST, 8, FALSE },
877 { BWRITERSPR_TEMP, 6, FALSE },
878 { BWRITERSPR_TEXTURE, 6, FALSE },
879 { BWRITERSPR_INPUT, 2, FALSE },
880 { ~0U, 0 } /* End tag */
881};
882
883static void asmparser_srcreg_ps_1_4(struct asm_parser *This,
884 struct instruction *instr, int num,
885 const struct shader_reg *src) {
886 struct shader_reg reg;
887
888 if(!check_reg_type(src, ps_1_4_reg_allowed)) {
889 asmparser_message(This, "Line %u: Source register %s not supported in PS 1.4\n",
890 This->line_no,
891 debug_print_srcreg(src));
892 set_parse_status(This, PARSE_ERR);
893 }
894 check_abs_srcmod(This, src->srcmod);
895 reg = map_oldps_register(src, TRUE);
896 memcpy(&instr->src[num], &reg, sizeof(reg));
897}
898
5786d3a0 899static const struct allowed_reg_type ps_2_0_reg_allowed[] = {
084d5f1f
MB
900 { BWRITERSPR_INPUT, 2, FALSE },
901 { BWRITERSPR_TEMP, 32, FALSE },
902 { BWRITERSPR_CONST, 32, FALSE },
903 { BWRITERSPR_CONSTINT, 16, FALSE },
904 { BWRITERSPR_CONSTBOOL, 16, FALSE },
905 { BWRITERSPR_SAMPLER, 16, FALSE },
906 { BWRITERSPR_TEXTURE, 8, FALSE },
907 { BWRITERSPR_COLOROUT, 4, FALSE },
908 { BWRITERSPR_DEPTHOUT, 1, FALSE },
5786d3a0
MB
909 { ~0U, 0 } /* End tag */
910};
911
912static void asmparser_srcreg_ps_2(struct asm_parser *This,
913 struct instruction *instr, int num,
914 const struct shader_reg *src) {
915 struct shader_reg reg;
916
917 if(!check_reg_type(src, ps_2_0_reg_allowed)) {
918 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.0\n",
919 This->line_no,
a5e55c15 920 debug_print_srcreg(src));
5786d3a0
MB
921 set_parse_status(This, PARSE_ERR);
922 }
923 check_legacy_srcmod(This, src->srcmod);
924 check_abs_srcmod(This, src->srcmod);
925 reg = map_oldps_register(src, TRUE);
926 memcpy(&instr->src[num], &reg, sizeof(reg));
927}
928
929static const struct allowed_reg_type ps_2_x_reg_allowed[] = {
084d5f1f
MB
930 { BWRITERSPR_INPUT, 2, FALSE },
931 { BWRITERSPR_TEMP, 32, FALSE },
932 { BWRITERSPR_CONST, 32, FALSE },
933 { BWRITERSPR_CONSTINT, 16, FALSE },
934 { BWRITERSPR_CONSTBOOL, 16, FALSE },
935 { BWRITERSPR_PREDICATE, 1, FALSE },
936 { BWRITERSPR_SAMPLER, 16, FALSE },
937 { BWRITERSPR_TEXTURE, 8, FALSE },
938 { BWRITERSPR_LABEL, 2048, FALSE },
939 { BWRITERSPR_COLOROUT, 4, FALSE },
940 { BWRITERSPR_DEPTHOUT, 1, FALSE },
5786d3a0
MB
941 { ~0U, 0 } /* End tag */
942};
943
944static void asmparser_srcreg_ps_2_x(struct asm_parser *This,
945 struct instruction *instr, int num,
946 const struct shader_reg *src) {
947 struct shader_reg reg;
948
949 if(!check_reg_type(src, ps_2_x_reg_allowed)) {
950 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.x\n",
951 This->line_no,
a5e55c15 952 debug_print_srcreg(src));
5786d3a0
MB
953 set_parse_status(This, PARSE_ERR);
954 }
955 check_legacy_srcmod(This, src->srcmod);
956 check_abs_srcmod(This, src->srcmod);
957 reg = map_oldps_register(src, TRUE);
958 memcpy(&instr->src[num], &reg, sizeof(reg));
959}
960
5cc00e82 961static const struct allowed_reg_type ps_3_reg_allowed[] = {
084d5f1f
MB
962 { BWRITERSPR_INPUT, 10, TRUE },
963 { BWRITERSPR_TEMP, 32, FALSE },
964 { BWRITERSPR_CONST, 224, FALSE },
965 { BWRITERSPR_CONSTINT, 16, FALSE },
966 { BWRITERSPR_CONSTBOOL, 16, FALSE },
967 { BWRITERSPR_PREDICATE, 1, FALSE },
968 { BWRITERSPR_SAMPLER, 16, FALSE },
969 { BWRITERSPR_MISCTYPE, 2, FALSE }, /* vPos and vFace */
970 { BWRITERSPR_LOOP, 1, FALSE },
971 { BWRITERSPR_LABEL, 2048, FALSE },
972 { BWRITERSPR_COLOROUT, 4, FALSE },
973 { BWRITERSPR_DEPTHOUT, 1, FALSE },
5cc00e82
MB
974 { ~0U, 0 } /* End tag */
975};
976
977static void asmparser_srcreg_ps_3(struct asm_parser *This,
978 struct instruction *instr, int num,
979 const struct shader_reg *src) {
980 if(!check_reg_type(src, ps_3_reg_allowed)) {
981 asmparser_message(This, "Line %u: Source register %s not supported in PS 3.0\n",
982 This->line_no,
a5e55c15 983 debug_print_srcreg(src));
5cc00e82
MB
984 set_parse_status(This, PARSE_ERR);
985 }
986 check_loop_swizzle(This, src);
987 check_legacy_srcmod(This, src->srcmod);
988 memcpy(&instr->src[num], src, sizeof(*src));
989}
990
913278c5
MB
991static void asmparser_dstreg_vs_1(struct asm_parser *This,
992 struct instruction *instr,
993 const struct shader_reg *dst) {
994 struct shader_reg reg;
995
996 if(!check_reg_type(dst, vs_1_reg_allowed)) {
997 asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\n",
998 This->line_no,
a5e55c15 999 debug_print_dstreg(dst));
913278c5
MB
1000 set_parse_status(This, PARSE_ERR);
1001 }
1002 check_ps_dstmod(This, instr->dstmod);
1003 check_shift_dstmod(This, instr->shift);
1004 reg = map_oldvs_register(dst);
1005 memcpy(&instr->dst, &reg, sizeof(reg));
1006 instr->has_dst = TRUE;
1007}
1008
5050f7c8
MB
1009static void asmparser_dstreg_vs_2(struct asm_parser *This,
1010 struct instruction *instr,
1011 const struct shader_reg *dst) {
1012 struct shader_reg reg;
1013
1014 if(!check_reg_type(dst, vs_2_reg_allowed)) {
1015 asmparser_message(This, "Line %u: Destination register %s not supported in VS 2.0\n",
1016 This->line_no,
a5e55c15 1017 debug_print_dstreg(dst));
5050f7c8
MB
1018 set_parse_status(This, PARSE_ERR);
1019 }
1020 check_ps_dstmod(This, instr->dstmod);
1021 check_shift_dstmod(This, instr->shift);
1022 reg = map_oldvs_register(dst);
1023 memcpy(&instr->dst, &reg, sizeof(reg));
1024 instr->has_dst = TRUE;
1025}
1026
95afbead
MB
1027static void asmparser_dstreg_vs_3(struct asm_parser *This,
1028 struct instruction *instr,
1029 const struct shader_reg *dst) {
c1f7faca
MB
1030 if(!check_reg_type(dst, vs_3_reg_allowed)) {
1031 asmparser_message(This, "Line %u: Destination register %s not supported in VS 3.0\n",
1032 This->line_no,
a5e55c15 1033 debug_print_dstreg(dst));
c1f7faca
MB
1034 set_parse_status(This, PARSE_ERR);
1035 }
1036 check_ps_dstmod(This, instr->dstmod);
1037 check_shift_dstmod(This, instr->shift);
95afbead
MB
1038 memcpy(&instr->dst, dst, sizeof(*dst));
1039 instr->has_dst = TRUE;
1040}
1041
d567a030
MB
1042static void asmparser_dstreg_ps_1_0123(struct asm_parser *This,
1043 struct instruction *instr,
1044 const struct shader_reg *dst) {
1045 struct shader_reg reg;
1046
1047 if(!check_reg_type(dst, ps_1_0123_reg_allowed)) {
1048 asmparser_message(This, "Line %u: Destination register %s not supported in PS 1\n",
1049 This->line_no,
1050 debug_print_dstreg(dst));
1051 set_parse_status(This, PARSE_ERR);
1052 }
1053 reg = map_oldps_register(dst, FALSE);
1054 memcpy(&instr->dst, &reg, sizeof(reg));
1055 instr->has_dst = TRUE;
1056}
1057
bfa39992
MB
1058static void asmparser_dstreg_ps_1_4(struct asm_parser *This,
1059 struct instruction *instr,
1060 const struct shader_reg *dst) {
1061 struct shader_reg reg;
1062
1063 if(!check_reg_type(dst, ps_1_4_reg_allowed)) {
1064 asmparser_message(This, "Line %u: Destination register %s not supported in PS 1\n",
1065 This->line_no,
1066 debug_print_dstreg(dst));
1067 set_parse_status(This, PARSE_ERR);
1068 }
383a7fe3 1069 reg = map_oldps_register(dst, TRUE);
bfa39992
MB
1070 memcpy(&instr->dst, &reg, sizeof(reg));
1071 instr->has_dst = TRUE;
1072}
1073
5786d3a0
MB
1074static void asmparser_dstreg_ps_2(struct asm_parser *This,
1075 struct instruction *instr,
1076 const struct shader_reg *dst) {
1077 struct shader_reg reg;
1078
1079 if(!check_reg_type(dst, ps_2_0_reg_allowed)) {
1080 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.0\n",
1081 This->line_no,
a5e55c15 1082 debug_print_dstreg(dst));
5786d3a0
MB
1083 set_parse_status(This, PARSE_ERR);
1084 }
1085 check_shift_dstmod(This, instr->shift);
1086 reg = map_oldps_register(dst, TRUE);
1087 memcpy(&instr->dst, &reg, sizeof(reg));
1088 instr->has_dst = TRUE;
1089}
1090
1091static void asmparser_dstreg_ps_2_x(struct asm_parser *This,
1092 struct instruction *instr,
1093 const struct shader_reg *dst) {
1094 struct shader_reg reg;
1095
1096 if(!check_reg_type(dst, ps_2_x_reg_allowed)) {
1097 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.x\n",
1098 This->line_no,
a5e55c15 1099 debug_print_dstreg(dst));
5786d3a0
MB
1100 set_parse_status(This, PARSE_ERR);
1101 }
1102 check_shift_dstmod(This, instr->shift);
1103 reg = map_oldps_register(dst, TRUE);
1104 memcpy(&instr->dst, &reg, sizeof(reg));
1105 instr->has_dst = TRUE;
1106}
1107
5cc00e82
MB
1108static void asmparser_dstreg_ps_3(struct asm_parser *This,
1109 struct instruction *instr,
1110 const struct shader_reg *dst) {
1111 if(!check_reg_type(dst, ps_3_reg_allowed)) {
1112 asmparser_message(This, "Line %u: Destination register %s not supported in PS 3.0\n",
1113 This->line_no,
a5e55c15 1114 debug_print_dstreg(dst));
5cc00e82
MB
1115 set_parse_status(This, PARSE_ERR);
1116 }
1117 check_shift_dstmod(This, instr->shift);
1118 memcpy(&instr->dst, dst, sizeof(*dst));
1119 instr->has_dst = TRUE;
1120}
1121
9847d287
MB
1122static void asmparser_predicate_supported(struct asm_parser *This,
1123 const struct shader_reg *predicate) {
1124 /* this sets the predicate of the last instruction added to the shader */
1125 if(!This->shader) return;
1126 if(This->shader->num_instrs == 0) ERR("Predicate without an instruction\n");
1127 This->shader->instr[This->shader->num_instrs - 1]->has_predicate = TRUE;
1128 memcpy(&This->shader->instr[This->shader->num_instrs - 1]->predicate, predicate, sizeof(*predicate));
1129}
1130
95afbead
MB
1131static void asmparser_predicate_unsupported(struct asm_parser *This,
1132 const struct shader_reg *predicate) {
1133 asmparser_message(This, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This->line_no);
1134 set_parse_status(This, PARSE_ERR);
1135}
1136
bfa39992
MB
1137static void asmparser_coissue_supported(struct asm_parser *This) {
1138 /* this sets the coissue flag of the last instruction added to the shader */
1139 if(!This->shader) return;
1140 if(This->shader->num_instrs == 0){
1141 asmparser_message(This, "Line %u: Coissue flag on the first shader instruction\n", This->line_no);
1142 set_parse_status(This, PARSE_ERR);
1143 }
1144 This->shader->instr[This->shader->num_instrs-1]->coissue = TRUE;
1145}
1146
95afbead
MB
1147static void asmparser_coissue_unsupported(struct asm_parser *This) {
1148 asmparser_message(This, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This->line_no);
1149 set_parse_status(This, PARSE_ERR);
1150}
1151
913278c5
MB
1152static const struct asmparser_backend parser_vs_1 = {
1153 asmparser_constF,
1154 asmparser_constI,
1155 asmparser_constB,
1156
1157 asmparser_dstreg_vs_1,
1158 asmparser_srcreg_vs_1,
1159
1160 asmparser_predicate_unsupported,
1161 asmparser_coissue_unsupported,
1162
0ea6f795 1163 asmparser_dcl_output_unsupported,
913278c5 1164 asmparser_dcl_input,
5a5844d4 1165 asmparser_dcl_sampler_unsupported,
913278c5
MB
1166
1167 asmparser_end,
1168
1169 asmparser_instr,
1170};
1171
5050f7c8
MB
1172static const struct asmparser_backend parser_vs_2 = {
1173 asmparser_constF,
1174 asmparser_constI,
1175 asmparser_constB,
1176
1177 asmparser_dstreg_vs_2,
1178 asmparser_srcreg_vs_2,
1179
1180 asmparser_predicate_supported,
1181 asmparser_coissue_unsupported,
1182
0ea6f795 1183 asmparser_dcl_output_unsupported,
5050f7c8 1184 asmparser_dcl_input,
5a5844d4 1185 asmparser_dcl_sampler_unsupported,
5050f7c8
MB
1186
1187 asmparser_end,
1188
1189 asmparser_instr,
1190};
1191
95afbead 1192static const struct asmparser_backend parser_vs_3 = {
dc1fa014 1193 asmparser_constF,
fa44f242 1194 asmparser_constI,
1371e71f 1195 asmparser_constB,
dc1fa014 1196
95afbead
MB
1197 asmparser_dstreg_vs_3,
1198 asmparser_srcreg_vs_3,
1199
9847d287 1200 asmparser_predicate_supported,
95afbead
MB
1201 asmparser_coissue_unsupported,
1202
b627d13e 1203 asmparser_dcl_output,
6cbd5114 1204 asmparser_dcl_input,
745b5fe8 1205 asmparser_dcl_sampler,
b627d13e 1206
95afbead
MB
1207 asmparser_end,
1208
1209 asmparser_instr,
1210};
1211
d567a030
MB
1212static const struct asmparser_backend parser_ps_1_0123 = {
1213 asmparser_constF,
1214 asmparser_constI,
1215 asmparser_constB,
1216
1217 asmparser_dstreg_ps_1_0123,
1218 asmparser_srcreg_ps_1_0123,
1219
1220 asmparser_predicate_unsupported,
1221 asmparser_coissue_supported,
1222
1223 asmparser_dcl_output_unsupported,
1224 asmparser_dcl_input_unsupported,
1225 asmparser_dcl_sampler_unsupported,
1226
1227 asmparser_end,
1228
1229 asmparser_instr,
1230};
1231
bfa39992
MB
1232static const struct asmparser_backend parser_ps_1_4 = {
1233 asmparser_constF,
1234 asmparser_constI,
1235 asmparser_constB,
1236
1237 asmparser_dstreg_ps_1_4,
1238 asmparser_srcreg_ps_1_4,
1239
1240 asmparser_predicate_unsupported,
1241 asmparser_coissue_supported,
1242
1243 asmparser_dcl_output_unsupported,
1244 asmparser_dcl_input_unsupported,
1245 asmparser_dcl_sampler_unsupported,
1246
1247 asmparser_end,
1248
1249 asmparser_instr,
1250};
1251
5786d3a0
MB
1252static const struct asmparser_backend parser_ps_2 = {
1253 asmparser_constF,
1254 asmparser_constI,
1255 asmparser_constB,
1256
1257 asmparser_dstreg_ps_2,
1258 asmparser_srcreg_ps_2,
1259
1260 asmparser_predicate_unsupported,
1261 asmparser_coissue_unsupported,
1262
0ea6f795 1263 asmparser_dcl_output_unsupported,
00951f84 1264 asmparser_dcl_input_ps_2,
5786d3a0
MB
1265 asmparser_dcl_sampler,
1266
1267 asmparser_end,
1268
1269 asmparser_instr,
1270};
1271
1272static const struct asmparser_backend parser_ps_2_x = {
1273 asmparser_constF,
1274 asmparser_constI,
1275 asmparser_constB,
1276
1277 asmparser_dstreg_ps_2_x,
1278 asmparser_srcreg_ps_2_x,
1279
1280 asmparser_predicate_supported,
1281 asmparser_coissue_unsupported,
1282
0ea6f795 1283 asmparser_dcl_output_unsupported,
00951f84 1284 asmparser_dcl_input_ps_2,
5786d3a0
MB
1285 asmparser_dcl_sampler,
1286
1287 asmparser_end,
1288
1289 asmparser_instr,
1290};
1291
5cc00e82
MB
1292static const struct asmparser_backend parser_ps_3 = {
1293 asmparser_constF,
1294 asmparser_constI,
1295 asmparser_constB,
1296
1297 asmparser_dstreg_ps_3,
1298 asmparser_srcreg_ps_3,
1299
1300 asmparser_predicate_supported,
1301 asmparser_coissue_unsupported,
1302
0ea6f795 1303 asmparser_dcl_output_unsupported,
5cc00e82
MB
1304 asmparser_dcl_input,
1305 asmparser_dcl_sampler,
1306
1307 asmparser_end,
1308
1309 asmparser_instr,
1310};
1311
5050f7c8 1312static void gen_oldvs_output(struct bwriter_shader *shader) {
9a8ffc91
MB
1313 record_declaration(shader, BWRITERDECLUSAGE_POSITION, 0, 0, TRUE, OPOS_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1314 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, TRUE, OT0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1315 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, TRUE, OT1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1316 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, TRUE, OT2_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1317 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, TRUE, OT3_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1318 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, TRUE, OT4_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1319 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, TRUE, OT5_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1320 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, TRUE, OT6_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1321 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, TRUE, OT7_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1322 record_declaration(shader, BWRITERDECLUSAGE_FOG, 0, 0, TRUE, OFOG_REG, OFOG_WRITEMASK, TRUE);
1323 record_declaration(shader, BWRITERDECLUSAGE_PSIZE, 0, 0, TRUE, OPTS_REG, OPTS_WRITEMASK, TRUE);
1324 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, TRUE, OD0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1325 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
5050f7c8
MB
1326}
1327
5786d3a0
MB
1328static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
1329 switch(texcoords) {
9a8ffc91
MB
1330 case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1331 case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1332 case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1333 case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1334 case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1335 case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1336 case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1337 case 1: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, FALSE, T0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
5786d3a0 1338 };
9a8ffc91
MB
1339 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, FALSE, C0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1340 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
5786d3a0
MB
1341}
1342
913278c5
MB
1343void create_vs10_parser(struct asm_parser *ret) {
1344 TRACE_(parsed_shader)("vs_1_0\n");
1345
1346 ret->shader = asm_alloc(sizeof(*ret->shader));
1347 if(!ret->shader) {
1348 ERR("Failed to allocate memory for the shader\n");
1349 set_parse_status(ret, PARSE_ERR);
1350 return;
1351 }
1352
1353 ret->shader->type = ST_VERTEX;
1354 ret->shader->version = BWRITERVS_VERSION(1, 0);
1355 ret->funcs = &parser_vs_1;
1356 gen_oldvs_output(ret->shader);
1357}
1358
1359void create_vs11_parser(struct asm_parser *ret) {
1360 TRACE_(parsed_shader)("vs_1_1\n");
1361
1362 ret->shader = asm_alloc(sizeof(*ret->shader));
1363 if(!ret->shader) {
1364 ERR("Failed to allocate memory for the shader\n");
1365 set_parse_status(ret, PARSE_ERR);
1366 return;
1367 }
1368
1369 ret->shader->type = ST_VERTEX;
1370 ret->shader->version = BWRITERVS_VERSION(1, 1);
1371 ret->funcs = &parser_vs_1;
1372 gen_oldvs_output(ret->shader);
1373}
1374
5050f7c8
MB
1375void create_vs20_parser(struct asm_parser *ret) {
1376 TRACE_(parsed_shader)("vs_2_0\n");
1377
1378 ret->shader = asm_alloc(sizeof(*ret->shader));
1379 if(!ret->shader) {
1380 ERR("Failed to allocate memory for the shader\n");
1381 set_parse_status(ret, PARSE_ERR);
1382 return;
1383 }
1384
1385 ret->shader->type = ST_VERTEX;
1386 ret->shader->version = BWRITERVS_VERSION(2, 0);
1387 ret->funcs = &parser_vs_2;
1388 gen_oldvs_output(ret->shader);
1389}
1390
1391void create_vs2x_parser(struct asm_parser *ret) {
1392 TRACE_(parsed_shader)("vs_2_x\n");
1393
1394 ret->shader = asm_alloc(sizeof(*ret->shader));
1395 if(!ret->shader) {
1396 ERR("Failed to allocate memory for the shader\n");
1397 set_parse_status(ret, PARSE_ERR);
1398 return;
1399 }
1400
1401 ret->shader->type = ST_VERTEX;
1402 ret->shader->version = BWRITERVS_VERSION(2, 1);
1403 ret->funcs = &parser_vs_2;
1404 gen_oldvs_output(ret->shader);
1405}
1406
95afbead
MB
1407void create_vs30_parser(struct asm_parser *ret) {
1408 TRACE_(parsed_shader)("vs_3_0\n");
1409
1410 ret->shader = asm_alloc(sizeof(*ret->shader));
1411 if(!ret->shader) {
1412 ERR("Failed to allocate memory for the shader\n");
1413 set_parse_status(ret, PARSE_ERR);
1414 return;
1415 }
1416
1417 ret->shader->type = ST_VERTEX;
1418 ret->shader->version = BWRITERVS_VERSION(3, 0);
1419 ret->funcs = &parser_vs_3;
1420}
5cc00e82 1421
d567a030
MB
1422void create_ps10_parser(struct asm_parser *ret) {
1423 TRACE_(parsed_shader)("ps_1_0\n");
1424
1425 ret->shader = asm_alloc(sizeof(*ret->shader));
1426 if(!ret->shader) {
1427 ERR("Failed to allocate memory for the shader\n");
1428 set_parse_status(ret, PARSE_ERR);
1429 return;
1430 }
1431
1432 ret->shader->type = ST_PIXEL;
1433 ret->shader->version = BWRITERPS_VERSION(1, 0);
1434 ret->funcs = &parser_ps_1_0123;
1435 gen_oldps_input(ret->shader, 4);
1436}
1437
1438void create_ps11_parser(struct asm_parser *ret) {
1439 TRACE_(parsed_shader)("ps_1_1\n");
1440
1441 ret->shader = asm_alloc(sizeof(*ret->shader));
1442 if(!ret->shader) {
1443 ERR("Failed to allocate memory for the shader\n");
1444 set_parse_status(ret, PARSE_ERR);
1445 return;
1446 }
1447
1448 ret->shader->type = ST_PIXEL;
1449 ret->shader->version = BWRITERPS_VERSION(1, 1);
1450 ret->funcs = &parser_ps_1_0123;
1451 gen_oldps_input(ret->shader, 4);
1452}
1453
1454void create_ps12_parser(struct asm_parser *ret) {
1455 TRACE_(parsed_shader)("ps_1_2\n");
1456
1457 ret->shader = asm_alloc(sizeof(*ret->shader));
1458 if(!ret->shader) {
1459 ERR("Failed to allocate memory for the shader\n");
1460 set_parse_status(ret, PARSE_ERR);
1461 return;
1462 }
1463
1464 ret->shader->type = ST_PIXEL;
1465 ret->shader->version = BWRITERPS_VERSION(1, 2);
1466 ret->funcs = &parser_ps_1_0123;
1467 gen_oldps_input(ret->shader, 4);
1468}
1469
1470void create_ps13_parser(struct asm_parser *ret) {
1471 TRACE_(parsed_shader)("ps_1_3\n");
1472
1473 ret->shader = asm_alloc(sizeof(*ret->shader));
1474 if(!ret->shader) {
1475 ERR("Failed to allocate memory for the shader\n");
1476 set_parse_status(ret, PARSE_ERR);
1477 return;
1478 }
1479
1480 ret->shader->type = ST_PIXEL;
1481 ret->shader->version = BWRITERPS_VERSION(1, 3);
1482 ret->funcs = &parser_ps_1_0123;
1483 gen_oldps_input(ret->shader, 4);
1484}
1485
bfa39992
MB
1486void create_ps14_parser(struct asm_parser *ret) {
1487 TRACE_(parsed_shader)("ps_1_4\n");
1488
1489 ret->shader = asm_alloc(sizeof(*ret->shader));
1490 if(!ret->shader) {
1491 ERR("Failed to allocate memory for the shader\n");
1492 set_parse_status(ret, PARSE_ERR);
1493 return;
1494 }
1495
1496 ret->shader->type = ST_PIXEL;
1497 ret->shader->version = BWRITERPS_VERSION(1, 4);
1498 ret->funcs = &parser_ps_1_4;
1499 gen_oldps_input(ret->shader, 6);
1500}
1501
5786d3a0
MB
1502void create_ps20_parser(struct asm_parser *ret) {
1503 TRACE_(parsed_shader)("ps_2_0\n");
1504
1505 ret->shader = asm_alloc(sizeof(*ret->shader));
1506 if(!ret->shader) {
1507 ERR("Failed to allocate memory for the shader\n");
1508 set_parse_status(ret, PARSE_ERR);
1509 return;
1510 }
1511
1512 ret->shader->type = ST_PIXEL;
1513 ret->shader->version = BWRITERPS_VERSION(2, 0);
1514 ret->funcs = &parser_ps_2;
1515 gen_oldps_input(ret->shader, 8);
1516}
1517
1518void create_ps2x_parser(struct asm_parser *ret) {
1519 TRACE_(parsed_shader)("ps_2_x\n");
1520
1521 ret->shader = asm_alloc(sizeof(*ret->shader));
1522 if(!ret->shader) {
1523 ERR("Failed to allocate memory for the shader\n");
1524 set_parse_status(ret, PARSE_ERR);
1525 return;
1526 }
1527
1528 ret->shader->type = ST_PIXEL;
1529 ret->shader->version = BWRITERPS_VERSION(2, 1);
1530 ret->funcs = &parser_ps_2_x;
1531 gen_oldps_input(ret->shader, 8);
1532}
1533
5cc00e82
MB
1534void create_ps30_parser(struct asm_parser *ret) {
1535 TRACE_(parsed_shader)("ps_3_0\n");
1536
1537 ret->shader = asm_alloc(sizeof(*ret->shader));
1538 if(!ret->shader) {
1539 ERR("Failed to allocate memory for the shader\n");
1540 set_parse_status(ret, PARSE_ERR);
1541 return;
1542 }
1543
1544 ret->shader->type = ST_PIXEL;
1545 ret->shader->version = BWRITERPS_VERSION(3, 0);
1546 ret->funcs = &parser_ps_3;
1547}