1 /* 2 * Direct3D shader assembler 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 "wine/debug.h" 24 25 #include "d3dcompiler_private.h" 26 27 WINE_DEFAULT_DEBUG_CHANNEL(asmshader); 28 29 struct asm_parser asm_ctx; 30 31 void WINAPIV asmparser_message(struct asm_parser *ctx, const char *fmt, ...) 32 { 33 __ms_va_list args; 34 35 __ms_va_start(args, fmt); 36 compilation_message(&ctx->messages, fmt, args); 37 __ms_va_end(args); 38 } 39 40 static void asmshader_error(char const *s) { 41 asmparser_message(&asm_ctx, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no, s); 42 set_parse_status(&asm_ctx.status, PARSE_ERR); 43 } 44 45 static void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) { 46 /* We can have an additional offset without true relative addressing 47 * ex. c2[ 4 ] */ 48 reg->regnum += rel->additional_offset; 49 if(!rel->has_rel_reg) { 50 reg->rel_reg = NULL; 51 } else { 52 reg->rel_reg = d3dcompiler_alloc(sizeof(*reg->rel_reg)); 53 if(!reg->rel_reg) { 54 return; 55 } 56 reg->rel_reg->type = rel->type; 57 reg->rel_reg->u.swizzle = rel->swizzle; 58 reg->rel_reg->regnum = rel->rel_regnum; 59 } 60 } 61 62 /* Needed lexer functions declarations */ 63 int asmshader_lex(void); 64 65 66 %} 67 68 %union { 69 struct { 70 float val; 71 BOOL integer; 72 } immval; 73 BOOL immbool; 74 unsigned int regnum; 75 struct shader_reg reg; 76 DWORD srcmod; 77 DWORD writemask; 78 struct { 79 DWORD writemask; 80 DWORD idx; 81 DWORD last; 82 } wm_components; 83 DWORD swizzle; 84 struct { 85 DWORD swizzle; 86 DWORD idx; 87 } sw_components; 88 DWORD component; 89 struct { 90 DWORD mod; 91 DWORD shift; 92 } modshift; 93 enum bwriter_comparison_type comptype; 94 struct { 95 DWORD dclusage; 96 unsigned int regnum; 97 } declaration; 98 enum bwritersampler_texture_type samplertype; 99 struct rel_reg rel_reg; 100 struct src_regs sregs; 101 } 102 103 /* Common instructions between vertex and pixel shaders */ 104 %token INSTR_ADD 105 %token INSTR_NOP 106 %token INSTR_MOV 107 %token INSTR_SUB 108 %token INSTR_MAD 109 %token INSTR_MUL 110 %token INSTR_RCP 111 %token INSTR_RSQ 112 %token INSTR_DP3 113 %token INSTR_DP4 114 %token INSTR_MIN 115 %token INSTR_MAX 116 %token INSTR_SLT 117 %token INSTR_SGE 118 %token INSTR_ABS 119 %token INSTR_EXP 120 %token INSTR_LOG 121 %token INSTR_EXPP 122 %token INSTR_LOGP 123 %token INSTR_DST 124 %token INSTR_LRP 125 %token INSTR_FRC 126 %token INSTR_POW 127 %token INSTR_CRS 128 %token INSTR_SGN 129 %token INSTR_NRM 130 %token INSTR_SINCOS 131 %token INSTR_M4x4 132 %token INSTR_M4x3 133 %token INSTR_M3x4 134 %token INSTR_M3x3 135 %token INSTR_M3x2 136 %token INSTR_DCL 137 %token INSTR_DEF 138 %token INSTR_DEFB 139 %token INSTR_DEFI 140 %token INSTR_REP 141 %token INSTR_ENDREP 142 %token INSTR_IF 143 %token INSTR_ELSE 144 %token INSTR_ENDIF 145 %token INSTR_BREAK 146 %token INSTR_BREAKP 147 %token INSTR_CALL 148 %token INSTR_CALLNZ 149 %token INSTR_LOOP 150 %token INSTR_RET 151 %token INSTR_ENDLOOP 152 %token INSTR_LABEL 153 %token INSTR_SETP 154 %token INSTR_TEXLDL 155 156 /* Vertex shader only instructions */ 157 %token INSTR_LIT 158 %token INSTR_MOVA 159 160 /* Pixel shader only instructions */ 161 %token INSTR_CND 162 %token INSTR_CMP 163 %token INSTR_DP2ADD 164 %token INSTR_TEXCOORD 165 %token INSTR_TEXCRD 166 %token INSTR_TEXKILL 167 %token INSTR_TEX 168 %token INSTR_TEXLD 169 %token INSTR_TEXBEM 170 %token INSTR_TEXBEML 171 %token INSTR_TEXREG2AR 172 %token INSTR_TEXREG2GB 173 %token INSTR_TEXREG2RGB 174 %token INSTR_TEXM3x2PAD 175 %token INSTR_TEXM3x2TEX 176 %token INSTR_TEXM3x3PAD 177 %token INSTR_TEXM3x3SPEC 178 %token INSTR_TEXM3x3VSPEC 179 %token INSTR_TEXM3x3TEX 180 %token INSTR_TEXDP3TEX 181 %token INSTR_TEXM3x2DEPTH 182 %token INSTR_TEXDP3 183 %token INSTR_TEXM3x3 184 %token INSTR_TEXDEPTH 185 %token INSTR_BEM 186 %token INSTR_DSX 187 %token INSTR_DSY 188 %token INSTR_TEXLDP 189 %token INSTR_TEXLDB 190 %token INSTR_TEXLDD 191 %token INSTR_PHASE 192 193 /* Registers */ 194 %token <regnum> REG_TEMP 195 %token <regnum> REG_OUTPUT 196 %token <regnum> REG_INPUT 197 %token <regnum> REG_CONSTFLOAT 198 %token <regnum> REG_CONSTINT 199 %token <regnum> REG_CONSTBOOL 200 %token <regnum> REG_TEXTURE 201 %token <regnum> REG_SAMPLER 202 %token <regnum> REG_TEXCRDOUT 203 %token REG_OPOS 204 %token REG_OFOG 205 %token REG_OPTS 206 %token <regnum> REG_VERTEXCOLOR 207 %token <regnum> REG_FRAGCOLOR 208 %token REG_FRAGDEPTH 209 %token REG_VPOS 210 %token REG_VFACE 211 %token REG_ADDRESS 212 %token REG_LOOP 213 %token REG_PREDICATE 214 %token <regnum> REG_LABEL 215 216 /* Version tokens */ 217 %token VER_VS10 218 %token VER_VS11 219 %token VER_VS20 220 %token VER_VS2X 221 %token VER_VS30 222 223 %token VER_PS10 224 %token VER_PS11 225 %token VER_PS12 226 %token VER_PS13 227 %token VER_PS14 228 %token VER_PS20 229 %token VER_PS2X 230 %token VER_PS30 231 232 /* Output modifiers */ 233 %token SHIFT_X2 234 %token SHIFT_X4 235 %token SHIFT_X8 236 %token SHIFT_D2 237 %token SHIFT_D4 238 %token SHIFT_D8 239 %token MOD_SAT 240 %token MOD_PP 241 %token MOD_CENTROID 242 243 /* Compare tokens */ 244 %token COMP_GT 245 %token COMP_LT 246 %token COMP_GE 247 %token COMP_LE 248 %token COMP_EQ 249 %token COMP_NE 250 251 /* Source register modifiers */ 252 %token SMOD_BIAS 253 %token SMOD_SCALEBIAS 254 %token SMOD_DZ 255 %token SMOD_DW 256 %token SMOD_ABS 257 %token SMOD_NOT 258 259 /* Sampler types */ 260 %token SAMPTYPE_1D 261 %token SAMPTYPE_2D 262 %token SAMPTYPE_CUBE 263 %token SAMPTYPE_VOLUME 264 265 /* Usage declaration tokens */ 266 %token <regnum> USAGE_POSITION 267 %token <regnum> USAGE_BLENDWEIGHT 268 %token <regnum> USAGE_BLENDINDICES 269 %token <regnum> USAGE_NORMAL 270 %token <regnum> USAGE_PSIZE 271 %token <regnum> USAGE_TEXCOORD 272 %token <regnum> USAGE_TANGENT 273 %token <regnum> USAGE_BINORMAL 274 %token <regnum> USAGE_TESSFACTOR 275 %token <regnum> USAGE_POSITIONT 276 %token <regnum> USAGE_COLOR 277 %token <regnum> USAGE_FOG 278 %token <regnum> USAGE_DEPTH 279 %token <regnum> USAGE_SAMPLE 280 281 /* Misc stuff */ 282 %token <component> COMPONENT 283 %token <immval> IMMVAL 284 %token <immbool> IMMBOOL 285 286 %type <reg> dreg_name 287 %type <reg> dreg 288 %type <reg> sreg_name 289 %type <reg> relreg_name 290 %type <reg> sreg 291 %type <srcmod> smod 292 %type <writemask> writemask 293 %type <wm_components> wm_components 294 %type <swizzle> swizzle 295 %type <sw_components> sw_components 296 %type <modshift> omods 297 %type <modshift> omodifier 298 %type <comptype> comp 299 %type <declaration> dclusage 300 %type <reg> dcl_inputreg 301 %type <samplertype> sampdcl 302 %type <rel_reg> rel_reg 303 %type <reg> predicate 304 %type <immval> immsum 305 %type <sregs> sregs 306 307 %% 308 309 shader: version_marker instructions 310 { 311 asm_ctx.funcs->end(&asm_ctx); 312 } 313 314 version_marker: VER_VS10 315 { 316 TRACE("Vertex shader 1.0\n"); 317 create_vs10_parser(&asm_ctx); 318 } 319 | VER_VS11 320 { 321 TRACE("Vertex shader 1.1\n"); 322 create_vs11_parser(&asm_ctx); 323 } 324 | VER_VS20 325 { 326 TRACE("Vertex shader 2.0\n"); 327 create_vs20_parser(&asm_ctx); 328 } 329 | VER_VS2X 330 { 331 TRACE("Vertex shader 2.x\n"); 332 create_vs2x_parser(&asm_ctx); 333 } 334 | VER_VS30 335 { 336 TRACE("Vertex shader 3.0\n"); 337 create_vs30_parser(&asm_ctx); 338 } 339 | VER_PS10 340 { 341 TRACE("Pixel shader 1.0\n"); 342 create_ps10_parser(&asm_ctx); 343 } 344 | VER_PS11 345 { 346 TRACE("Pixel shader 1.1\n"); 347 create_ps11_parser(&asm_ctx); 348 } 349 | VER_PS12 350 { 351 TRACE("Pixel shader 1.2\n"); 352 create_ps12_parser(&asm_ctx); 353 } 354 | VER_PS13 355 { 356 TRACE("Pixel shader 1.3\n"); 357 create_ps13_parser(&asm_ctx); 358 } 359 | VER_PS14 360 { 361 TRACE("Pixel shader 1.4\n"); 362 create_ps14_parser(&asm_ctx); 363 } 364 | VER_PS20 365 { 366 TRACE("Pixel shader 2.0\n"); 367 create_ps20_parser(&asm_ctx); 368 } 369 | VER_PS2X 370 { 371 TRACE("Pixel shader 2.x\n"); 372 create_ps2x_parser(&asm_ctx); 373 } 374 | VER_PS30 375 { 376 TRACE("Pixel shader 3.0\n"); 377 create_ps30_parser(&asm_ctx); 378 } 379 380 instructions: /* empty */ 381 | instructions complexinstr 382 { 383 /* Nothing to do */ 384 } 385 386 complexinstr: instruction 387 { 388 389 } 390 | predicate instruction 391 { 392 TRACE("predicate\n"); 393 asm_ctx.funcs->predicate(&asm_ctx, &$1); 394 } 395 | '+' instruction 396 { 397 TRACE("coissue\n"); 398 asm_ctx.funcs->coissue(&asm_ctx); 399 } 400 401 instruction: INSTR_ADD omods dreg ',' sregs 402 { 403 TRACE("ADD\n"); 404 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ADD, $2.mod, $2.shift, 0, &$3, &$5, 2); 405 } 406 | INSTR_NOP 407 { 408 TRACE("NOP\n"); 409 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NOP, 0, 0, 0, 0, 0, 0); 410 } 411 | INSTR_MOV omods dreg ',' sregs 412 { 413 TRACE("MOV\n"); 414 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOV, $2.mod, $2.shift, 0, &$3, &$5, 1); 415 } 416 | INSTR_SUB omods dreg ',' sregs 417 { 418 TRACE("SUB\n"); 419 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SUB, $2.mod, $2.shift, 0, &$3, &$5, 2); 420 } 421 | INSTR_MAD omods dreg ',' sregs 422 { 423 TRACE("MAD\n"); 424 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAD, $2.mod, $2.shift, 0, &$3, &$5, 3); 425 } 426 | INSTR_MUL omods dreg ',' sregs 427 { 428 TRACE("MUL\n"); 429 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MUL, $2.mod, $2.shift, 0, &$3, &$5, 2); 430 } 431 | INSTR_RCP omods dreg ',' sregs 432 { 433 TRACE("RCP\n"); 434 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RCP, $2.mod, $2.shift, 0, &$3, &$5, 1); 435 } 436 | INSTR_RSQ omods dreg ',' sregs 437 { 438 TRACE("RSQ\n"); 439 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RSQ, $2.mod, $2.shift, 0, &$3, &$5, 1); 440 } 441 | INSTR_DP3 omods dreg ',' sregs 442 { 443 TRACE("DP3\n"); 444 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP3, $2.mod, $2.shift, 0, &$3, &$5, 2); 445 } 446 | INSTR_DP4 omods dreg ',' sregs 447 { 448 TRACE("DP4\n"); 449 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP4, $2.mod, $2.shift, 0, &$3, &$5, 2); 450 } 451 | INSTR_MIN omods dreg ',' sregs 452 { 453 TRACE("MIN\n"); 454 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MIN, $2.mod, $2.shift, 0, &$3, &$5, 2); 455 } 456 | INSTR_MAX omods dreg ',' sregs 457 { 458 TRACE("MAX\n"); 459 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MAX, $2.mod, $2.shift, 0, &$3, &$5, 2); 460 } 461 | INSTR_SLT omods dreg ',' sregs 462 { 463 TRACE("SLT\n"); 464 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SLT, $2.mod, $2.shift, 0, &$3, &$5, 2); 465 } 466 | INSTR_SGE omods dreg ',' sregs 467 { 468 TRACE("SGE\n"); 469 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGE, $2.mod, $2.shift, 0, &$3, &$5, 2); 470 } 471 | INSTR_ABS omods dreg ',' sregs 472 { 473 TRACE("ABS\n"); 474 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ABS, $2.mod, $2.shift, 0, &$3, &$5, 1); 475 } 476 | INSTR_EXP omods dreg ',' sregs 477 { 478 TRACE("EXP\n"); 479 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXP, $2.mod, $2.shift, 0, &$3, &$5, 1); 480 } 481 | INSTR_LOG omods dreg ',' sregs 482 { 483 TRACE("LOG\n"); 484 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOG, $2.mod, $2.shift, 0, &$3, &$5, 1); 485 } 486 | INSTR_LOGP omods dreg ',' sregs 487 { 488 TRACE("LOGP\n"); 489 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOGP, $2.mod, $2.shift, 0, &$3, &$5, 1); 490 } 491 | INSTR_EXPP omods dreg ',' sregs 492 { 493 TRACE("EXPP\n"); 494 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_EXPP, $2.mod, $2.shift, 0, &$3, &$5, 1); 495 } 496 | INSTR_DST omods dreg ',' sregs 497 { 498 TRACE("DST\n"); 499 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DST, $2.mod, $2.shift, 0, &$3, &$5, 2); 500 } 501 | INSTR_LRP omods dreg ',' sregs 502 { 503 TRACE("LRP\n"); 504 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LRP, $2.mod, $2.shift, 0, &$3, &$5, 3); 505 } 506 | INSTR_FRC omods dreg ',' sregs 507 { 508 TRACE("FRC\n"); 509 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_FRC, $2.mod, $2.shift, 0, &$3, &$5, 1); 510 } 511 | INSTR_POW omods dreg ',' sregs 512 { 513 TRACE("POW\n"); 514 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_POW, $2.mod, $2.shift, 0, &$3, &$5, 2); 515 } 516 | INSTR_CRS omods dreg ',' sregs 517 { 518 TRACE("CRS\n"); 519 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CRS, $2.mod, $2.shift, 0, &$3, &$5, 2); 520 } 521 | INSTR_SGN omods dreg ',' sregs 522 { 523 TRACE("SGN\n"); 524 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SGN, $2.mod, $2.shift, 0, &$3, &$5, 3); 525 } 526 | INSTR_NRM omods dreg ',' sregs 527 { 528 TRACE("NRM\n"); 529 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_NRM, $2.mod, $2.shift, 0, &$3, &$5, 1); 530 } 531 | INSTR_SINCOS omods dreg ',' sregs 532 { 533 TRACE("SINCOS\n"); 534 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SINCOS, $2.mod, $2.shift, 0, &$3, &$5, 1); 535 } 536 | INSTR_M4x4 omods dreg ',' sregs 537 { 538 TRACE("M4x4\n"); 539 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x4, $2.mod, $2.shift, 0, &$3, &$5, 2); 540 } 541 | INSTR_M4x3 omods dreg ',' sregs 542 { 543 TRACE("M4x3\n"); 544 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M4x3, $2.mod, $2.shift, 0, &$3, &$5, 2); 545 } 546 | INSTR_M3x4 omods dreg ',' sregs 547 { 548 TRACE("M3x4\n"); 549 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x4, $2.mod, $2.shift, 0, &$3, &$5, 2); 550 } 551 | INSTR_M3x3 omods dreg ',' sregs 552 { 553 TRACE("M3x3\n"); 554 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x3, $2.mod, $2.shift, 0, &$3, &$5, 2); 555 } 556 | INSTR_M3x2 omods dreg ',' sregs 557 { 558 TRACE("M3x2\n"); 559 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x2, $2.mod, $2.shift, 0, &$3, &$5, 2); 560 } 561 | INSTR_DCL dclusage REG_OUTPUT 562 { 563 struct shader_reg reg; 564 TRACE("Output reg declaration\n"); 565 ZeroMemory(®, sizeof(reg)); 566 reg.type = BWRITERSPR_OUTPUT; 567 reg.regnum = $3; 568 reg.rel_reg = NULL; 569 reg.srcmod = 0; 570 reg.u.writemask = BWRITERSP_WRITEMASK_ALL; 571 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, ®); 572 } 573 | INSTR_DCL dclusage REG_OUTPUT writemask 574 { 575 struct shader_reg reg; 576 TRACE("Output reg declaration\n"); 577 ZeroMemory(®, sizeof(reg)); 578 reg.type = BWRITERSPR_OUTPUT; 579 reg.regnum = $3; 580 reg.rel_reg = NULL; 581 reg.srcmod = 0; 582 reg.u.writemask = $4; 583 asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, ®); 584 } 585 | INSTR_DCL dclusage omods dcl_inputreg 586 { 587 struct shader_reg reg; 588 TRACE("Input reg declaration\n"); 589 if($3.shift != 0) { 590 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n", 591 asm_ctx.line_no); 592 set_parse_status(&asm_ctx.status, PARSE_ERR); 593 } 594 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) || 595 asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) { 596 asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n", 597 asm_ctx.line_no); 598 set_parse_status(&asm_ctx.status, PARSE_ERR); 599 } 600 ZeroMemory(®, sizeof(reg)); 601 reg.type = $4.type; 602 reg.regnum = $4.regnum; 603 reg.rel_reg = NULL; 604 reg.srcmod = 0; 605 reg.u.writemask = BWRITERSP_WRITEMASK_ALL; 606 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, ®); 607 } 608 | INSTR_DCL dclusage omods dcl_inputreg writemask 609 { 610 struct shader_reg reg; 611 TRACE("Input reg declaration\n"); 612 if($3.shift != 0) { 613 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n", 614 asm_ctx.line_no); 615 set_parse_status(&asm_ctx.status, PARSE_ERR); 616 } 617 if(asm_ctx.shader->version == BWRITERPS_VERSION(2, 0) || 618 asm_ctx.shader->version == BWRITERPS_VERSION(2, 1)) { 619 asmparser_message(&asm_ctx, "Line %u: Declaration not supported in PS 2\n", 620 asm_ctx.line_no); 621 set_parse_status(&asm_ctx.status, PARSE_ERR); 622 } 623 ZeroMemory(®, sizeof(reg)); 624 reg.type = $4.type; 625 reg.regnum = $4.regnum; 626 reg.rel_reg = NULL; 627 reg.srcmod = 0; 628 reg.u.writemask = $5; 629 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, $3.mod, ®); 630 } 631 | INSTR_DCL omods dcl_inputreg 632 { 633 struct shader_reg reg; 634 TRACE("Input reg declaration\n"); 635 if($2.shift != 0) { 636 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n", 637 asm_ctx.line_no); 638 set_parse_status(&asm_ctx.status, PARSE_ERR); 639 } 640 if(asm_ctx.shader->type != ST_PIXEL) { 641 asmparser_message(&asm_ctx, "Line %u: Declaration needs a semantic\n", 642 asm_ctx.line_no); 643 set_parse_status(&asm_ctx.status, PARSE_ERR); 644 } 645 ZeroMemory(®, sizeof(reg)); 646 reg.type = $3.type; 647 reg.regnum = $3.regnum; 648 reg.rel_reg = NULL; 649 reg.srcmod = 0; 650 reg.u.writemask = BWRITERSP_WRITEMASK_ALL; 651 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, ®); 652 } 653 | INSTR_DCL omods dcl_inputreg writemask 654 { 655 struct shader_reg reg; 656 TRACE("Input reg declaration\n"); 657 if($2.shift != 0) { 658 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n", 659 asm_ctx.line_no); 660 set_parse_status(&asm_ctx.status, PARSE_ERR); 661 } 662 if(asm_ctx.shader->type != ST_PIXEL) { 663 asmparser_message(&asm_ctx, "Line %u: Declaration needs a semantic\n", 664 asm_ctx.line_no); 665 set_parse_status(&asm_ctx.status, PARSE_ERR); 666 } 667 ZeroMemory(®, sizeof(reg)); 668 reg.type = $3.type; 669 reg.regnum = $3.regnum; 670 reg.rel_reg = NULL; 671 reg.srcmod = 0; 672 reg.u.writemask = $4; 673 asm_ctx.funcs->dcl_input(&asm_ctx, 0, 0, $2.mod, ®); 674 } 675 | INSTR_DCL sampdcl omods REG_SAMPLER 676 { 677 TRACE("Sampler declared\n"); 678 if($3.shift != 0) { 679 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n", 680 asm_ctx.line_no); 681 set_parse_status(&asm_ctx.status, PARSE_ERR); 682 } 683 asm_ctx.funcs->dcl_sampler(&asm_ctx, $2, $3.mod, $4, asm_ctx.line_no); 684 } 685 | INSTR_DCL omods REG_SAMPLER 686 { 687 TRACE("Sampler declared\n"); 688 if($2.shift != 0) { 689 asmparser_message(&asm_ctx, "Line %u: Shift modifier not allowed here\n", 690 asm_ctx.line_no); 691 set_parse_status(&asm_ctx.status, PARSE_ERR); 692 } 693 if(asm_ctx.shader->type != ST_PIXEL) { 694 asmparser_message(&asm_ctx, "Line %u: Declaration needs a sampler type\n", 695 asm_ctx.line_no); 696 set_parse_status(&asm_ctx.status, PARSE_ERR); 697 } 698 asm_ctx.funcs->dcl_sampler(&asm_ctx, BWRITERSTT_UNKNOWN, $2.mod, $3, asm_ctx.line_no); 699 } 700 | INSTR_DCL sampdcl omods dcl_inputreg 701 { 702 TRACE("Error rule: sampler decl of input reg\n"); 703 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of input regs is not valid\n", 704 asm_ctx.line_no); 705 set_parse_status(&asm_ctx.status, PARSE_WARN); 706 } 707 | INSTR_DCL sampdcl omods REG_OUTPUT 708 { 709 TRACE("Error rule: sampler decl of output reg\n"); 710 asmparser_message(&asm_ctx, "Line %u: Sampler declarations of output regs is not valid\n", 711 asm_ctx.line_no); 712 set_parse_status(&asm_ctx.status, PARSE_WARN); 713 } 714 | INSTR_DEF REG_CONSTFLOAT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL 715 { 716 asm_ctx.funcs->constF(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val); 717 } 718 | INSTR_DEFI REG_CONSTINT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL 719 { 720 asm_ctx.funcs->constI(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val); 721 } 722 | INSTR_DEFB REG_CONSTBOOL ',' IMMBOOL 723 { 724 asm_ctx.funcs->constB(&asm_ctx, $2, $4); 725 } 726 | INSTR_REP sregs 727 { 728 TRACE("REP\n"); 729 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_REP, 0, 0, 0, 0, &$2, 1); 730 } 731 | INSTR_ENDREP 732 { 733 TRACE("ENDREP\n"); 734 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDREP, 0, 0, 0, 0, 0, 0); 735 } 736 | INSTR_IF sregs 737 { 738 TRACE("IF\n"); 739 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IF, 0, 0, 0, 0, &$2, 1); 740 } 741 | INSTR_IF comp sregs 742 { 743 TRACE("IFC\n"); 744 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_IFC, 0, 0, $2, 0, &$3, 2); 745 } 746 | INSTR_ELSE 747 { 748 TRACE("ELSE\n"); 749 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ELSE, 0, 0, 0, 0, 0, 0); 750 } 751 | INSTR_ENDIF 752 { 753 TRACE("ENDIF\n"); 754 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDIF, 0, 0, 0, 0, 0, 0); 755 } 756 | INSTR_BREAK 757 { 758 TRACE("BREAK\n"); 759 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAK, 0, 0, 0, 0, 0, 0); 760 } 761 | INSTR_BREAK comp sregs 762 { 763 TRACE("BREAKC\n"); 764 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKC, 0, 0, $2, 0, &$3, 2); 765 } 766 | INSTR_BREAKP sregs 767 { 768 TRACE("BREAKP\n"); 769 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BREAKP, 0, 0, 0, 0, &$2, 1); 770 } 771 | INSTR_CALL sregs 772 { 773 TRACE("CALL\n"); 774 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALL, 0, 0, 0, 0, &$2, 1); 775 } 776 | INSTR_CALLNZ sregs 777 { 778 TRACE("CALLNZ\n"); 779 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CALLNZ, 0, 0, 0, 0, &$2, 2); 780 } 781 | INSTR_LOOP sregs 782 { 783 TRACE("LOOP\n"); 784 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LOOP, 0, 0, 0, 0, &$2, 2); 785 } 786 | INSTR_RET 787 { 788 TRACE("RET\n"); 789 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_RET, 0, 0, 0, 0, 0, 0); 790 } 791 | INSTR_ENDLOOP 792 { 793 TRACE("ENDLOOP\n"); 794 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_ENDLOOP, 0, 0, 0, 0, 0, 0); 795 } 796 | INSTR_LABEL sregs 797 { 798 TRACE("LABEL\n"); 799 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LABEL, 0, 0, 0, 0, &$2, 1); 800 } 801 | INSTR_SETP comp dreg ',' sregs 802 { 803 TRACE("SETP\n"); 804 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_SETP, 0, 0, $2, &$3, &$5, 2); 805 } 806 | INSTR_TEXLDL omods dreg ',' sregs 807 { 808 TRACE("TEXLDL\n"); 809 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDL, $2.mod, $2.shift, 0, &$3, &$5, 2); 810 } 811 | INSTR_LIT omods dreg ',' sregs 812 { 813 TRACE("LIT\n"); 814 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_LIT, $2.mod, $2.shift, 0, &$3, &$5, 1); 815 } 816 | INSTR_MOVA omods dreg ',' sregs 817 { 818 TRACE("MOVA\n"); 819 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOVA, $2.mod, $2.shift, 0, &$3, &$5, 1); 820 } 821 | INSTR_CND omods dreg ',' sregs 822 { 823 TRACE("CND\n"); 824 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CND, $2.mod, $2.shift, 0, &$3, &$5, 3); 825 } 826 | INSTR_CMP omods dreg ',' sregs 827 { 828 TRACE("CMP\n"); 829 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_CMP, $2.mod, $2.shift, 0, &$3, &$5, 3); 830 } 831 | INSTR_DP2ADD omods dreg ',' sregs 832 { 833 TRACE("DP2ADD\n"); 834 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DP2ADD, $2.mod, $2.shift, 0, &$3, &$5, 3); 835 } 836 | INSTR_TEXCOORD omods dreg 837 { 838 TRACE("TEXCOORD\n"); 839 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXCOORD, $2.mod, $2.shift, 0, &$3, 0, 0); 840 } 841 | INSTR_TEXCRD omods dreg ',' sregs 842 { 843 TRACE("TEXCRD\n"); 844 /* texcoord and texcrd share the same opcode */ 845 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXCOORD, $2.mod, $2.shift, 0, &$3, &$5, 1); 846 } 847 | INSTR_TEXKILL dreg 848 { 849 TRACE("TEXKILL\n"); 850 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXKILL, 0, 0, 0, &$2, 0, 0); 851 } 852 | INSTR_TEX omods dreg 853 { 854 TRACE("TEX\n"); 855 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, 0, 0); 856 } 857 | INSTR_TEXDEPTH omods dreg 858 { 859 TRACE("TEXDEPTH\n"); 860 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDEPTH, $2.mod, $2.shift, 0, &$3, 0, 0); 861 } 862 | INSTR_TEXLD omods dreg ',' sregs 863 { 864 TRACE("TEXLD\n"); 865 /* There is more than one acceptable syntax for texld: 866 with 1 sreg (PS 1.4) or 867 with 2 sregs (PS 2.0+) 868 Moreover, texld shares the same opcode as the tex instruction, 869 so there are a total of 3 valid syntaxes 870 These variations are handled in asmparser.c */ 871 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, &$5, 2); 872 } 873 | INSTR_TEXLDP omods dreg ',' sregs 874 { 875 TRACE("TEXLDP\n"); 876 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDP, $2.mod, $2.shift, 0, &$3, &$5, 2); 877 } 878 | INSTR_TEXLDB omods dreg ',' sregs 879 { 880 TRACE("TEXLDB\n"); 881 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDB, $2.mod, $2.shift, 0, &$3, &$5, 2); 882 } 883 | INSTR_TEXBEM omods dreg ',' sregs 884 { 885 TRACE("TEXBEM\n"); 886 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXBEM, $2.mod, $2.shift, 0, &$3, &$5, 1); 887 } 888 | INSTR_TEXBEML omods dreg ',' sregs 889 { 890 TRACE("TEXBEML\n"); 891 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXBEML, $2.mod, $2.shift, 0, &$3, &$5, 1); 892 } 893 | INSTR_TEXREG2AR omods dreg ',' sregs 894 { 895 TRACE("TEXREG2AR\n"); 896 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2AR, $2.mod, $2.shift, 0, &$3, &$5, 1); 897 } 898 | INSTR_TEXREG2GB omods dreg ',' sregs 899 { 900 TRACE("TEXREG2GB\n"); 901 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2GB, $2.mod, $2.shift, 0, &$3, &$5, 1); 902 } 903 | INSTR_TEXREG2RGB omods dreg ',' sregs 904 { 905 TRACE("TEXREG2RGB\n"); 906 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXREG2RGB, $2.mod, $2.shift, 0, &$3, &$5, 1); 907 } 908 | INSTR_TEXM3x2PAD omods dreg ',' sregs 909 { 910 TRACE("TEXM3x2PAD\n"); 911 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2PAD, $2.mod, $2.shift, 0, &$3, &$5, 1); 912 } 913 | INSTR_TEXM3x3PAD omods dreg ',' sregs 914 { 915 TRACE("INSTR_TEXM3x3PAD\n"); 916 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3PAD, $2.mod, $2.shift, 0, &$3, &$5, 1); 917 } 918 | INSTR_TEXM3x3SPEC omods dreg ',' sregs 919 { 920 TRACE("TEXM3x3SPEC\n"); 921 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3SPEC, $2.mod, $2.shift, 0, &$3, &$5, 2); 922 } 923 | INSTR_TEXM3x3VSPEC omods dreg ',' sregs 924 { 925 TRACE("TEXM3x3VSPEC\n"); 926 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3VSPEC, $2.mod, $2.shift, 0, &$3, &$5, 1); 927 } 928 | INSTR_TEXM3x3TEX omods dreg ',' sregs 929 { 930 TRACE("TEXM3x3TEX\n"); 931 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3TEX, $2.mod, $2.shift, 0, &$3, &$5, 1); 932 } 933 | INSTR_TEXDP3TEX omods dreg ',' sregs 934 { 935 TRACE("TEXDP3TEX\n"); 936 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDP3TEX, $2.mod, $2.shift, 0, &$3, &$5, 1); 937 } 938 | INSTR_TEXM3x2DEPTH omods dreg ',' sregs 939 { 940 TRACE("TEXM3x2DEPTH\n"); 941 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2DEPTH, $2.mod, $2.shift, 0, &$3, &$5, 1); 942 } 943 | INSTR_TEXM3x2TEX omods dreg ',' sregs 944 { 945 TRACE("TEXM3x2TEX\n"); 946 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x2TEX, $2.mod, $2.shift, 0, &$3, &$5, 1); 947 } 948 | INSTR_TEXDP3 omods dreg ',' sregs 949 { 950 TRACE("TEXDP3\n"); 951 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXDP3, $2.mod, $2.shift, 0, &$3, &$5, 1); 952 } 953 | INSTR_TEXM3x3 omods dreg ',' sregs 954 { 955 TRACE("TEXM3x3\n"); 956 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXM3x3, $2.mod, $2.shift, 0, &$3, &$5, 1); 957 } 958 | INSTR_BEM omods dreg ',' sregs 959 { 960 TRACE("BEM\n"); 961 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_BEM, $2.mod, $2.shift, 0, &$3, &$5, 2); 962 } 963 | INSTR_DSX omods dreg ',' sregs 964 { 965 TRACE("DSX\n"); 966 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSX, $2.mod, $2.shift, 0, &$3, &$5, 1); 967 } 968 | INSTR_DSY omods dreg ',' sregs 969 { 970 TRACE("DSY\n"); 971 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_DSY, $2.mod, $2.shift, 0, &$3, &$5, 1); 972 } 973 | INSTR_TEXLDD omods dreg ',' sregs 974 { 975 TRACE("TEXLDD\n"); 976 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_TEXLDD, $2.mod, $2.shift, 0, &$3, &$5, 4); 977 } 978 | INSTR_PHASE 979 { 980 TRACE("PHASE\n"); 981 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_PHASE, 0, 0, 0, 0, 0, 0); 982 } 983 984 985 dreg: dreg_name rel_reg 986 { 987 $$.regnum = $1.regnum; 988 $$.type = $1.type; 989 $$.u.writemask = BWRITERSP_WRITEMASK_ALL; 990 $$.srcmod = BWRITERSPSM_NONE; 991 set_rel_reg(&$$, &$2); 992 } 993 | dreg_name writemask 994 { 995 $$.regnum = $1.regnum; 996 $$.type = $1.type; 997 $$.u.writemask = $2; 998 $$.srcmod = BWRITERSPSM_NONE; 999 $$.rel_reg = NULL; 1000 } 1001 1002 dreg_name: REG_TEMP 1003 { 1004 $$.regnum = $1; $$.type = BWRITERSPR_TEMP; 1005 } 1006 | REG_OUTPUT 1007 { 1008 $$.regnum = $1; $$.type = BWRITERSPR_OUTPUT; 1009 } 1010 | REG_INPUT 1011 { 1012 $$.regnum = $1; $$.type = BWRITERSPR_INPUT; 1013 } 1014 | REG_CONSTFLOAT 1015 { 1016 asmparser_message(&asm_ctx, "Line %u: Register c%u is not a valid destination register\n", 1017 asm_ctx.line_no, $1); 1018 set_parse_status(&asm_ctx.status, PARSE_WARN); 1019 } 1020 | REG_CONSTINT 1021 { 1022 asmparser_message(&asm_ctx, "Line %u: Register i%u is not a valid destination register\n", 1023 asm_ctx.line_no, $1); 1024 set_parse_status(&asm_ctx.status, PARSE_WARN); 1025 } 1026 | REG_CONSTBOOL 1027 { 1028 asmparser_message(&asm_ctx, "Line %u: Register b%u is not a valid destination register\n", 1029 asm_ctx.line_no, $1); 1030 set_parse_status(&asm_ctx.status, PARSE_WARN); 1031 } 1032 | REG_TEXTURE 1033 { 1034 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE; 1035 } 1036 | REG_TEXCRDOUT 1037 { 1038 $$.regnum = $1; $$.type = BWRITERSPR_TEXCRDOUT; 1039 } 1040 | REG_SAMPLER 1041 { 1042 asmparser_message(&asm_ctx, "Line %u: Register s%u is not a valid destination register\n", 1043 asm_ctx.line_no, $1); 1044 set_parse_status(&asm_ctx.status, PARSE_WARN); 1045 } 1046 | REG_OPOS 1047 { 1048 $$.regnum = BWRITERSRO_POSITION; $$.type = BWRITERSPR_RASTOUT; 1049 } 1050 | REG_OPTS 1051 { 1052 $$.regnum = BWRITERSRO_POINT_SIZE; $$.type = BWRITERSPR_RASTOUT; 1053 } 1054 | REG_OFOG 1055 { 1056 $$.regnum = BWRITERSRO_FOG; $$.type = BWRITERSPR_RASTOUT; 1057 } 1058 | REG_VERTEXCOLOR 1059 { 1060 $$.regnum = $1; $$.type = BWRITERSPR_ATTROUT; 1061 } 1062 | REG_FRAGCOLOR 1063 { 1064 $$.regnum = $1; $$.type = BWRITERSPR_COLOROUT; 1065 } 1066 | REG_FRAGDEPTH 1067 { 1068 $$.regnum = 0; $$.type = BWRITERSPR_DEPTHOUT; 1069 } 1070 | REG_PREDICATE 1071 { 1072 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE; 1073 } 1074 | REG_VPOS 1075 { 1076 asmparser_message(&asm_ctx, "Line %u: Register vPos is not a valid destination register\n", 1077 asm_ctx.line_no); 1078 set_parse_status(&asm_ctx.status, PARSE_WARN); 1079 } 1080 | REG_VFACE 1081 { 1082 asmparser_message(&asm_ctx, "Line %u: Register vFace is not a valid destination register\n", 1083 asm_ctx.line_no); 1084 set_parse_status(&asm_ctx.status, PARSE_WARN); 1085 } 1086 | REG_ADDRESS 1087 { 1088 /* index 0 is hardcoded for the addr register */ 1089 $$.regnum = 0; $$.type = BWRITERSPR_ADDR; 1090 } 1091 | REG_LOOP 1092 { 1093 asmparser_message(&asm_ctx, "Line %u: Register aL is not a valid destination register\n", 1094 asm_ctx.line_no); 1095 set_parse_status(&asm_ctx.status, PARSE_WARN); 1096 } 1097 1098 writemask: '.' wm_components 1099 { 1100 if($2.writemask == SWIZZLE_ERR) { 1101 asmparser_message(&asm_ctx, "Line %u: Invalid writemask specified\n", 1102 asm_ctx.line_no); 1103 set_parse_status(&asm_ctx.status, PARSE_ERR); 1104 /* Provide a correct writemask to prevent following complaints */ 1105 $$ = BWRITERSP_WRITEMASK_ALL; 1106 } 1107 else { 1108 $$ = $2.writemask; 1109 TRACE("Writemask: %x\n", $$); 1110 } 1111 } 1112 1113 wm_components: COMPONENT 1114 { 1115 $$.writemask = 1 << $1; 1116 $$.last = $1; 1117 $$.idx = 1; 1118 } 1119 | wm_components COMPONENT 1120 { 1121 if($1.writemask == SWIZZLE_ERR || $1.idx == 4) 1122 /* Wrong writemask */ 1123 $$.writemask = SWIZZLE_ERR; 1124 else { 1125 if($2 <= $1.last) 1126 $$.writemask = SWIZZLE_ERR; 1127 else { 1128 $$.writemask = $1.writemask | (1 << $2); 1129 $$.idx = $1.idx + 1; 1130 } 1131 } 1132 } 1133 1134 swizzle: /* empty */ 1135 { 1136 $$ = BWRITERVS_NOSWIZZLE; 1137 TRACE("Default swizzle: %08x\n", $$); 1138 } 1139 | '.' sw_components 1140 { 1141 if($2.swizzle == SWIZZLE_ERR) { 1142 asmparser_message(&asm_ctx, "Line %u: Invalid swizzle\n", 1143 asm_ctx.line_no); 1144 set_parse_status(&asm_ctx.status, PARSE_ERR); 1145 /* Provide a correct swizzle to prevent following complaints */ 1146 $$ = BWRITERVS_NOSWIZZLE; 1147 } 1148 else { 1149 DWORD last, i; 1150 1151 $$ = $2.swizzle << BWRITERVS_SWIZZLE_SHIFT; 1152 /* Fill the swizzle by extending the last component */ 1153 last = ($2.swizzle >> 2 * ($2.idx - 1)) & 0x03; 1154 for(i = $2.idx; i < 4; i++){ 1155 $$ |= last << (BWRITERVS_SWIZZLE_SHIFT + 2 * i); 1156 } 1157 TRACE("Got a swizzle: %08x\n", $$); 1158 } 1159 } 1160 1161 sw_components: COMPONENT 1162 { 1163 $$.swizzle = $1; 1164 $$.idx = 1; 1165 } 1166 | sw_components COMPONENT 1167 { 1168 if($1.idx == 4) { 1169 /* Too many sw_components */ 1170 $$.swizzle = SWIZZLE_ERR; 1171 $$.idx = 4; 1172 } 1173 else { 1174 $$.swizzle = $1.swizzle | ($2 << 2 * $1.idx); 1175 $$.idx = $1.idx + 1; 1176 } 1177 } 1178 1179 omods: /* Empty */ 1180 { 1181 $$.mod = 0; 1182 $$.shift = 0; 1183 } 1184 | omods omodifier 1185 { 1186 $$.mod = $1.mod | $2.mod; 1187 if($1.shift && $2.shift) { 1188 asmparser_message(&asm_ctx, "Line %u: More than one shift flag\n", 1189 asm_ctx.line_no); 1190 set_parse_status(&asm_ctx.status, PARSE_ERR); 1191 $$.shift = $1.shift; 1192 } else { 1193 $$.shift = $1.shift | $2.shift; 1194 } 1195 } 1196 1197 omodifier: SHIFT_X2 1198 { 1199 $$.mod = 0; 1200 $$.shift = 1; 1201 } 1202 | SHIFT_X4 1203 { 1204 $$.mod = 0; 1205 $$.shift = 2; 1206 } 1207 | SHIFT_X8 1208 { 1209 $$.mod = 0; 1210 $$.shift = 3; 1211 } 1212 | SHIFT_D2 1213 { 1214 $$.mod = 0; 1215 $$.shift = 15; 1216 } 1217 | SHIFT_D4 1218 { 1219 $$.mod = 0; 1220 $$.shift = 14; 1221 } 1222 | SHIFT_D8 1223 { 1224 $$.mod = 0; 1225 $$.shift = 13; 1226 } 1227 | MOD_SAT 1228 { 1229 $$.mod = BWRITERSPDM_SATURATE; 1230 $$.shift = 0; 1231 } 1232 | MOD_PP 1233 { 1234 $$.mod = BWRITERSPDM_PARTIALPRECISION; 1235 $$.shift = 0; 1236 } 1237 | MOD_CENTROID 1238 { 1239 $$.mod = BWRITERSPDM_MSAMPCENTROID; 1240 $$.shift = 0; 1241 } 1242 1243 sregs: sreg 1244 { 1245 $$.reg[0] = $1; 1246 $$.count = 1; 1247 } 1248 | sregs ',' sreg 1249 { 1250 if($$.count == MAX_SRC_REGS){ 1251 asmparser_message(&asm_ctx, "Line %u: Too many source registers in this instruction\n", 1252 asm_ctx.line_no); 1253 set_parse_status(&asm_ctx.status, PARSE_ERR); 1254 } 1255 else 1256 $$.reg[$$.count++] = $3; 1257 } 1258 1259 sreg: sreg_name rel_reg swizzle 1260 { 1261 $$.type = $1.type; 1262 $$.regnum = $1.regnum; 1263 $$.u.swizzle = $3; 1264 $$.srcmod = BWRITERSPSM_NONE; 1265 set_rel_reg(&$$, &$2); 1266 } 1267 | sreg_name rel_reg smod swizzle 1268 { 1269 $$.type = $1.type; 1270 $$.regnum = $1.regnum; 1271 set_rel_reg(&$$, &$2); 1272 $$.srcmod = $3; 1273 $$.u.swizzle = $4; 1274 } 1275 | '-' sreg_name rel_reg swizzle 1276 { 1277 $$.type = $2.type; 1278 $$.regnum = $2.regnum; 1279 $$.srcmod = BWRITERSPSM_NEG; 1280 set_rel_reg(&$$, &$3); 1281 $$.u.swizzle = $4; 1282 } 1283 | '-' sreg_name rel_reg smod swizzle 1284 { 1285 $$.type = $2.type; 1286 $$.regnum = $2.regnum; 1287 set_rel_reg(&$$, &$3); 1288 switch($4) { 1289 case BWRITERSPSM_BIAS: $$.srcmod = BWRITERSPSM_BIASNEG; break; 1290 case BWRITERSPSM_X2: $$.srcmod = BWRITERSPSM_X2NEG; break; 1291 case BWRITERSPSM_SIGN: $$.srcmod = BWRITERSPSM_SIGNNEG; break; 1292 case BWRITERSPSM_ABS: $$.srcmod = BWRITERSPSM_ABSNEG; break; 1293 case BWRITERSPSM_DZ: 1294 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DZ\n", 1295 asm_ctx.line_no); 1296 set_parse_status(&asm_ctx.status, PARSE_ERR); 1297 break; 1298 case BWRITERSPSM_DW: 1299 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: NEG and DW\n", 1300 asm_ctx.line_no); 1301 set_parse_status(&asm_ctx.status, PARSE_ERR); 1302 break; 1303 default: 1304 FIXME("Unhandled combination of NEGATE and %u\n", $4); 1305 } 1306 $$.u.swizzle = $5; 1307 } 1308 | IMMVAL '-' sreg_name rel_reg swizzle 1309 { 1310 if($1.val != 1.0 || (!$1.integer)) { 1311 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP, " 1312 "%g - reg found\n", asm_ctx.line_no, $1.val); 1313 set_parse_status(&asm_ctx.status, PARSE_ERR); 1314 } 1315 /* Complement - not compatible with other source modifiers */ 1316 $$.type = $3.type; 1317 $$.regnum = $3.regnum; 1318 $$.srcmod = BWRITERSPSM_COMP; 1319 set_rel_reg(&$$, &$4); 1320 $$.u.swizzle = $5; 1321 } 1322 | IMMVAL '-' sreg_name rel_reg smod swizzle 1323 { 1324 /* For nicer error reporting */ 1325 if($1.val != 1.0 || (!$1.integer)) { 1326 asmparser_message(&asm_ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP\n", 1327 asm_ctx.line_no); 1328 set_parse_status(&asm_ctx.status, PARSE_ERR); 1329 } else { 1330 asmparser_message(&asm_ctx, "Line %u: Incompatible source modifiers: D3DSPSM_COMP and %s\n", 1331 asm_ctx.line_no, 1332 debug_print_srcmod($5)); 1333 set_parse_status(&asm_ctx.status, PARSE_ERR); 1334 } 1335 } 1336 | SMOD_NOT sreg_name swizzle 1337 { 1338 $$.type = $2.type; 1339 $$.regnum = $2.regnum; 1340 $$.rel_reg = NULL; 1341 $$.srcmod = BWRITERSPSM_NOT; 1342 $$.u.swizzle = $3; 1343 } 1344 1345 rel_reg: /* empty */ 1346 { 1347 $$.has_rel_reg = FALSE; 1348 $$.additional_offset = 0; 1349 } 1350 | '[' immsum ']' 1351 { 1352 $$.has_rel_reg = FALSE; 1353 $$.additional_offset = $2.val; 1354 } 1355 | '[' relreg_name swizzle ']' 1356 { 1357 $$.has_rel_reg = TRUE; 1358 $$.type = $2.type; 1359 $$.additional_offset = 0; 1360 $$.rel_regnum = $2.regnum; 1361 $$.swizzle = $3; 1362 } 1363 | '[' immsum '+' relreg_name swizzle ']' 1364 { 1365 $$.has_rel_reg = TRUE; 1366 $$.type = $4.type; 1367 $$.additional_offset = $2.val; 1368 $$.rel_regnum = $4.regnum; 1369 $$.swizzle = $5; 1370 } 1371 | '[' relreg_name swizzle '+' immsum ']' 1372 { 1373 $$.has_rel_reg = TRUE; 1374 $$.type = $2.type; 1375 $$.additional_offset = $5.val; 1376 $$.rel_regnum = $2.regnum; 1377 $$.swizzle = $3; 1378 } 1379 | '[' immsum '+' relreg_name swizzle '+' immsum ']' 1380 { 1381 $$.has_rel_reg = TRUE; 1382 $$.type = $4.type; 1383 $$.additional_offset = $2.val + $7.val; 1384 $$.rel_regnum = $4.regnum; 1385 $$.swizzle = $5; 1386 } 1387 1388 immsum: IMMVAL 1389 { 1390 if(!$1.integer) { 1391 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n", 1392 asm_ctx.line_no, $1.val); 1393 set_parse_status(&asm_ctx.status, PARSE_ERR); 1394 } 1395 $$.val = $1.val; 1396 } 1397 | immsum '+' IMMVAL 1398 { 1399 if(!$3.integer) { 1400 asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n", 1401 asm_ctx.line_no, $3.val); 1402 set_parse_status(&asm_ctx.status, PARSE_ERR); 1403 } 1404 $$.val = $1.val + $3.val; 1405 } 1406 1407 smod: SMOD_BIAS 1408 { 1409 $$ = BWRITERSPSM_BIAS; 1410 } 1411 | SHIFT_X2 1412 { 1413 $$ = BWRITERSPSM_X2; 1414 } 1415 | SMOD_SCALEBIAS 1416 { 1417 $$ = BWRITERSPSM_SIGN; 1418 } 1419 | SMOD_DZ 1420 { 1421 $$ = BWRITERSPSM_DZ; 1422 } 1423 | SMOD_DW 1424 { 1425 $$ = BWRITERSPSM_DW; 1426 } 1427 | SMOD_ABS 1428 { 1429 $$ = BWRITERSPSM_ABS; 1430 } 1431 1432 relreg_name: REG_ADDRESS 1433 { 1434 $$.regnum = 0; $$.type = BWRITERSPR_ADDR; 1435 } 1436 | REG_LOOP 1437 { 1438 $$.regnum = 0; $$.type = BWRITERSPR_LOOP; 1439 } 1440 1441 sreg_name: REG_TEMP 1442 { 1443 $$.regnum = $1; $$.type = BWRITERSPR_TEMP; 1444 } 1445 | REG_OUTPUT 1446 { 1447 asmparser_message(&asm_ctx, "Line %u: Register o%u is not a valid source register\n", 1448 asm_ctx.line_no, $1); 1449 set_parse_status(&asm_ctx.status, PARSE_WARN); 1450 } 1451 | REG_INPUT 1452 { 1453 $$.regnum = $1; $$.type = BWRITERSPR_INPUT; 1454 } 1455 | REG_CONSTFLOAT 1456 { 1457 $$.regnum = $1; $$.type = BWRITERSPR_CONST; 1458 } 1459 | REG_CONSTINT 1460 { 1461 $$.regnum = $1; $$.type = BWRITERSPR_CONSTINT; 1462 } 1463 | REG_CONSTBOOL 1464 { 1465 $$.regnum = $1; $$.type = BWRITERSPR_CONSTBOOL; 1466 } 1467 | REG_TEXTURE 1468 { 1469 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE; 1470 } 1471 | REG_TEXCRDOUT 1472 { 1473 asmparser_message(&asm_ctx, "Line %u: Register oT%u is not a valid source register\n", 1474 asm_ctx.line_no, $1); 1475 set_parse_status(&asm_ctx.status, PARSE_WARN); 1476 } 1477 | REG_SAMPLER 1478 { 1479 $$.regnum = $1; $$.type = BWRITERSPR_SAMPLER; 1480 } 1481 | REG_OPOS 1482 { 1483 asmparser_message(&asm_ctx, "Line %u: Register oPos is not a valid source register\n", 1484 asm_ctx.line_no); 1485 set_parse_status(&asm_ctx.status, PARSE_WARN); 1486 } 1487 | REG_OFOG 1488 { 1489 asmparser_message(&asm_ctx, "Line %u: Register oFog is not a valid source register\n", 1490 asm_ctx.line_no); 1491 set_parse_status(&asm_ctx.status, PARSE_WARN); 1492 } 1493 | REG_VERTEXCOLOR 1494 { 1495 asmparser_message(&asm_ctx, "Line %u: Register oD%u is not a valid source register\n", 1496 asm_ctx.line_no, $1); 1497 set_parse_status(&asm_ctx.status, PARSE_WARN); 1498 } 1499 | REG_FRAGCOLOR 1500 { 1501 asmparser_message(&asm_ctx, "Line %u: Register oC%u is not a valid source register\n", 1502 asm_ctx.line_no, $1); 1503 set_parse_status(&asm_ctx.status, PARSE_WARN); 1504 } 1505 | REG_FRAGDEPTH 1506 { 1507 asmparser_message(&asm_ctx, "Line %u: Register oDepth is not a valid source register\n", 1508 asm_ctx.line_no); 1509 set_parse_status(&asm_ctx.status, PARSE_WARN); 1510 } 1511 | REG_PREDICATE 1512 { 1513 $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE; 1514 } 1515 | REG_VPOS 1516 { 1517 $$.regnum = 0; $$.type = BWRITERSPR_MISCTYPE; 1518 } 1519 | REG_VFACE 1520 { 1521 $$.regnum = 1; $$.type = BWRITERSPR_MISCTYPE; 1522 } 1523 | REG_ADDRESS 1524 { 1525 $$.regnum = 0; $$.type = BWRITERSPR_ADDR; 1526 } 1527 | REG_LOOP 1528 { 1529 $$.regnum = 0; $$.type = BWRITERSPR_LOOP; 1530 } 1531 | REG_LABEL 1532 { 1533 $$.regnum = $1; $$.type = BWRITERSPR_LABEL; 1534 } 1535 1536 comp: COMP_GT { $$ = BWRITER_COMPARISON_GT; } 1537 | COMP_LT { $$ = BWRITER_COMPARISON_LT; } 1538 | COMP_GE { $$ = BWRITER_COMPARISON_GE; } 1539 | COMP_LE { $$ = BWRITER_COMPARISON_LE; } 1540 | COMP_EQ { $$ = BWRITER_COMPARISON_EQ; } 1541 | COMP_NE { $$ = BWRITER_COMPARISON_NE; } 1542 1543 dclusage: USAGE_POSITION 1544 { 1545 TRACE("dcl_position%u\n", $1); 1546 $$.regnum = $1; 1547 $$.dclusage = BWRITERDECLUSAGE_POSITION; 1548 } 1549 | USAGE_BLENDWEIGHT 1550 { 1551 TRACE("dcl_blendweight%u\n", $1); 1552 $$.regnum = $1; 1553 $$.dclusage = BWRITERDECLUSAGE_BLENDWEIGHT; 1554 } 1555 | USAGE_BLENDINDICES 1556 { 1557 TRACE("dcl_blendindices%u\n", $1); 1558 $$.regnum = $1; 1559 $$.dclusage = BWRITERDECLUSAGE_BLENDINDICES; 1560 } 1561 | USAGE_NORMAL 1562 { 1563 TRACE("dcl_normal%u\n", $1); 1564 $$.regnum = $1; 1565 $$.dclusage = BWRITERDECLUSAGE_NORMAL; 1566 } 1567 | USAGE_PSIZE 1568 { 1569 TRACE("dcl_psize%u\n", $1); 1570 $$.regnum = $1; 1571 $$.dclusage = BWRITERDECLUSAGE_PSIZE; 1572 } 1573 | USAGE_TEXCOORD 1574 { 1575 TRACE("dcl_texcoord%u\n", $1); 1576 $$.regnum = $1; 1577 $$.dclusage = BWRITERDECLUSAGE_TEXCOORD; 1578 } 1579 | USAGE_TANGENT 1580 { 1581 TRACE("dcl_tangent%u\n", $1); 1582 $$.regnum = $1; 1583 $$.dclusage = BWRITERDECLUSAGE_TANGENT; 1584 } 1585 | USAGE_BINORMAL 1586 { 1587 TRACE("dcl_binormal%u\n", $1); 1588 $$.regnum = $1; 1589 $$.dclusage = BWRITERDECLUSAGE_BINORMAL; 1590 } 1591 | USAGE_TESSFACTOR 1592 { 1593 TRACE("dcl_tessfactor%u\n", $1); 1594 $$.regnum = $1; 1595 $$.dclusage = BWRITERDECLUSAGE_TESSFACTOR; 1596 } 1597 | USAGE_POSITIONT 1598 { 1599 TRACE("dcl_positiont%u\n", $1); 1600 $$.regnum = $1; 1601 $$.dclusage = BWRITERDECLUSAGE_POSITIONT; 1602 } 1603 | USAGE_COLOR 1604 { 1605 TRACE("dcl_color%u\n", $1); 1606 $$.regnum = $1; 1607 $$.dclusage = BWRITERDECLUSAGE_COLOR; 1608 } 1609 | USAGE_FOG 1610 { 1611 TRACE("dcl_fog%u\n", $1); 1612 $$.regnum = $1; 1613 $$.dclusage = BWRITERDECLUSAGE_FOG; 1614 } 1615 | USAGE_DEPTH 1616 { 1617 TRACE("dcl_depth%u\n", $1); 1618 $$.regnum = $1; 1619 $$.dclusage = BWRITERDECLUSAGE_DEPTH; 1620 } 1621 | USAGE_SAMPLE 1622 { 1623 TRACE("dcl_sample%u\n", $1); 1624 $$.regnum = $1; 1625 $$.dclusage = BWRITERDECLUSAGE_SAMPLE; 1626 } 1627 1628 dcl_inputreg: REG_INPUT 1629 { 1630 $$.regnum = $1; $$.type = BWRITERSPR_INPUT; 1631 } 1632 | REG_TEXTURE 1633 { 1634 $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE; 1635 } 1636 1637 sampdcl: SAMPTYPE_1D 1638 { 1639 $$ = BWRITERSTT_1D; 1640 } 1641 | SAMPTYPE_2D 1642 { 1643 $$ = BWRITERSTT_2D; 1644 } 1645 | SAMPTYPE_CUBE 1646 { 1647 $$ = BWRITERSTT_CUBE; 1648 } 1649 | SAMPTYPE_VOLUME 1650 { 1651 $$ = BWRITERSTT_VOLUME; 1652 } 1653 1654 predicate: '(' REG_PREDICATE swizzle ')' 1655 { 1656 $$.type = BWRITERSPR_PREDICATE; 1657 $$.regnum = 0; 1658 $$.rel_reg = NULL; 1659 $$.srcmod = BWRITERSPSM_NONE; 1660 $$.u.swizzle = $3; 1661 } 1662 | '(' SMOD_NOT REG_PREDICATE swizzle ')' 1663 { 1664 $$.type = BWRITERSPR_PREDICATE; 1665 $$.regnum = 0; 1666 $$.rel_reg = NULL; 1667 $$.srcmod = BWRITERSPSM_NOT; 1668 $$.u.swizzle = $4; 1669 } 1670 1671 %% 1672 1673 struct bwriter_shader *parse_asm_shader(char **messages) 1674 { 1675 struct bwriter_shader *ret = NULL; 1676 1677 asm_ctx.shader = NULL; 1678 asm_ctx.status = PARSE_SUCCESS; 1679 asm_ctx.messages.size = asm_ctx.messages.capacity = 0; 1680 asm_ctx.line_no = 1; 1681 1682 asmshader_parse(); 1683 1684 if (asm_ctx.status != PARSE_ERR) 1685 ret = asm_ctx.shader; 1686 else if (asm_ctx.shader) 1687 SlDeleteShader(asm_ctx.shader); 1688 1689 if (messages) 1690 { 1691 if (asm_ctx.messages.size) 1692 { 1693 /* Shrink the buffer to the used size */ 1694 *messages = d3dcompiler_realloc(asm_ctx.messages.string, asm_ctx.messages.size + 1); 1695 if (!*messages) 1696 { 1697 ERR("Out of memory, no messages reported\n"); 1698 d3dcompiler_free(asm_ctx.messages.string); 1699 } 1700 } 1701 else 1702 { 1703 *messages = NULL; 1704 } 1705 } 1706 else 1707 { 1708 if (asm_ctx.messages.capacity) 1709 d3dcompiler_free(asm_ctx.messages.string); 1710 } 1711 1712 return ret; 1713 } 1714