[5/18] d3dx9: Add base assembler lexer and parser
Matteo Bruni
matteo.mystral at gmail.com
Sun Aug 16 12:51:52 CDT 2009
-------------- next part --------------
From 2a73fabcc0e8f8c95a11509f6a21ee2048b069e9 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Sat, 15 Aug 2009 18:27:58 +0200
Subject: d3dx9: Add base assembler lexer and parser
---
dlls/d3dx9_36/Makefile.in | 6 +
dlls/d3dx9_36/asmparser.c | 156 +++++
dlls/d3dx9_36/asmshader.l | 552 ++++++++++++++++
dlls/d3dx9_36/asmshader.y | 1606 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 2320 insertions(+), 0 deletions(-)
create mode 100644 dlls/d3dx9_36/asmparser.c
create mode 100644 dlls/d3dx9_36/asmshader.l
create mode 100644 dlls/d3dx9_36/asmshader.y
diff --git a/dlls/d3dx9_36/Makefile.in b/dlls/d3dx9_36/Makefile.in
index 88ac1d7..87788d8 100644
--- a/dlls/d3dx9_36/Makefile.in
+++ b/dlls/d3dx9_36/Makefile.in
@@ -7,6 +7,9 @@ IMPORTLIB = d3dx9
IMPORTS = d3d9 gdi32 user32 kernel32
C_SRCS = \
+ asmparser.c \
+ asmutils.c \
+ bytecodewriter.c \
core.c \
d3dx9_36_main.c \
font.c \
@@ -17,6 +20,9 @@ C_SRCS = \
surface.c \
util.c
+LEX_SRCS = asmshader.l
+BISON_SRCS = asmshader.y
+
RC_SRCS = version.rc
@MAKE_DLL_RULES@
diff --git a/dlls/d3dx9_36/asmparser.c b/dlls/d3dx9_36/asmparser.c
new file mode 100644
index 0000000..a880b62
--- /dev/null
+++ b/dlls/d3dx9_36/asmparser.c
@@ -0,0 +1,156 @@
+/*
+ * Direct3D asm shader parser
+ *
+ * Copyright 2008 Stefan Dösinger
+ * Copyright 2009 Matteo Bruni
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+
+#include "config.h"
+#include "wine/port.h"
+#include "wine/debug.h"
+
+#include "d3dx9_36_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
+WINE_DECLARE_DEBUG_CHANNEL(parsed_shader);
+
+
+/****************************************************************
+ * Common(non-version specific) shader parser control code *
+ ****************************************************************/
+
+static void asmparser_end(struct asm_parser *This) {
+ TRACE("Finalizing shader\n");
+}
+
+static void asmparser_constF(struct asm_parser *This, DWORD reg, float x, float y, float z, float w) {
+ if(!This->shader) return;
+ TRACE("Adding float constant %u at pos %u\n", reg, This->shader->num_cf);
+ TRACE_(parsed_shader)("def c%u, %f, %f, %f, %f\n", reg, x, y, z, w);
+ if(!add_constF(This->shader, reg, x, y, z, w)) {
+ ERR("Out of memory\n");
+ set_parse_status(This, PARSE_ERR);
+ }
+}
+
+static void asmparser_constB(struct asm_parser *This, DWORD reg, BOOL x) {
+ if(!This->shader) return;
+ TRACE("Adding boolean constant %u at pos %u\n", reg, This->shader->num_cb);
+ TRACE_(parsed_shader)("def b%u, %s\n", reg, x ? "true" : "false");
+ if(!add_constB(This->shader, reg, x)) {
+ ERR("Out of memory\n");
+ set_parse_status(This, PARSE_ERR);
+ }
+}
+
+static void asmparser_constI(struct asm_parser *This, DWORD reg, INT x, INT y, INT z, INT w) {
+ if(!This->shader) return;
+ TRACE("Adding integer constant %u at pos %u\n", reg, This->shader->num_ci);
+ TRACE_(parsed_shader)("def i%u, %d, %d, %d, %d\n", reg, x, y, z, w);
+ if(!add_constI(This->shader, reg, x, y, z, w)) {
+ ERR("Out of memory\n");
+ set_parse_status(This, PARSE_ERR);
+ }
+}
+
+static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num,
+ const struct shader_reg *reg) {
+ if(!This->shader) return;
+ if(This->shader->type == ST_PIXEL) {
+ asmparser_message(This, "Line %u: Output register declared in a pixel shader\n", This->line_no);
+ set_parse_status(This, PARSE_ERR);
+ }
+ if(!record_declaration(This->shader, usage, num, TRUE, reg->regnum, reg->writemask)) {
+ ERR("Out of memory\n");
+ set_parse_status(This, PARSE_ERR);
+ }
+}
+
+static void asmparser_dcl_input(struct asm_parser *This, DWORD usage, DWORD num,
+ const struct shader_reg *reg) {
+ if(!This->shader) return;
+ if(!record_declaration(This->shader, usage, num, FALSE, reg->regnum, reg->writemask)) {
+ ERR("Out of memory\n");
+ set_parse_status(This, PARSE_ERR);
+ }
+}
+
+static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype, DWORD regnum, unsigned int line_no) {
+ if(!This->shader) return;
+ if(!record_sampler(This->shader, samptype, regnum, line_no)) {
+ ERR("Out of memory\n");
+ set_parse_status(This, PARSE_ERR);
+ }
+}
+
+static void asmparser_instr(struct asm_parser *This, DWORD opcode,
+ DWORD mod, DWORD shift,
+ BWRITER_COMPARISON_TYPE comp,
+ const struct shader_reg *dst,
+ const struct src_regs *srcs, int expectednsrcs) {
+ struct instruction *instr;
+ unsigned int i;
+ BOOL firstreg = TRUE;
+ unsigned int src_count = srcs ? srcs->count : 0;
+
+ if(!This->shader) return;
+
+ TRACE_(parsed_shader)("%s%s%s%s ", debug_print_opcode(opcode),
+ debug_print_dstmod(mod),
+ debug_print_shift(shift),
+ debug_print_comp(comp));
+ if(dst) {
+ TRACE_(parsed_shader)("%s", debug_print_dstreg(dst, This->shader->type));
+ firstreg = FALSE;
+ }
+ for(i = 0; i < src_count; i++) {
+ if(!firstreg) TRACE_(parsed_shader)(", ");
+ else firstreg = FALSE;
+ TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i],
+ This->shader->type));
+ }
+ TRACE_(parsed_shader)("\n");
+
+ if(src_count != expectednsrcs) {
+ asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no);
+ set_parse_status(This, PARSE_ERR);
+ return;
+ }
+
+ instr = alloc_instr(src_count);
+ if(!instr) {
+ ERR("Error allocating memory for the instruction\n");
+ set_parse_status(This, PARSE_ERR);
+ return;
+ }
+
+ instr->opcode = opcode;
+ instr->dstmod = mod;
+ instr->shift = shift;
+ instr->comptype = comp;
+ if(dst) This->funcs->dstreg(This, instr, dst);
+ for(i = 0; i < src_count; i++) {
+ This->funcs->srcreg(This, instr, i, &srcs->reg[i]);
+ }
+
+ if(!add_instruction(This->shader, instr)) {
+ ERR("Out of memory\n");
+ set_parse_status(This, PARSE_ERR);
+ }
+}
+
diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l
new file mode 100644
index 0000000..824cdbc
--- /dev/null
+++ b/dlls/d3dx9_36/asmshader.l
@@ -0,0 +1,552 @@
+/*
+ * Direct3D shader assembler
+ *
+ * Copyright 2008 Stefan Dösinger
+ * Copyright 2009 Matteo Bruni
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+%{
+#include "config.h"
+#include "wine/port.h"
+#include "wine/debug.h"
+
+#include "d3dx9_36_private.h"
+#include "asmshader.tab.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
+%}
+
+%option reentrant bison-bridge
+%option noyywrap
+%option prefix="asmshader_"
+%option noinput nounput
+
+/* Swizzles and writemasks consist of a dot and up to 4 x, y, z or w characters,
+ * or up to 4 a, r, g, b characters. There are different rules for swizzles and
+ * writemasks wrt repetition, those are handled in the grammar. color(argb) and
+ * coordinate(xyzw) components cannot be mixed.
+ */
+SWIZZLE \.(([w-z]+)|((a|r|g|b)+))
+
+/* Registers */
+REG_TEMP r[0-9]+
+/* for relative addressing in the form o[x], v[x] and c[x] */
+REG_OUTPUT o[0-9]*
+REG_INPUT v[0-9]*
+REG_CONSTFLOAT c[0-9]*
+REG_CONSTINT i[0-9]+
+REG_CONSTBOOL b[0-9]+
+REG_TEXTURE t[0-9]+
+REG_TEXCRDOUT oT[0-9]+
+REG_SAMPLER s[0-9]+
+REG_OPOS oPos
+REG_OFOG oFog
+REG_OPTS oPts
+REG_VERTEXCOLOR oD0|oD1
+REG_FRAGCOLOR oC[0-9]+
+REG_FRAGDEPTH oDepth
+REG_VPOS vPos
+REG_VFACE vFace
+REG_ADDRESS a0
+REG_LOOP aL
+REG_PREDICATE p0
+/* Not really a register, but it is considered as such */
+REG_LABEL l[0-9]+
+
+DCL_POSITION _position[0-9]*
+DCL_BLENDWEIGHT _blendweight[0-9]*
+DCL_BLENDINDICES _blendindices[0-9]*
+DCL_NORMAL _normal[0-9]*
+DCL_PSIZE _psize[0-9]*
+DCL_TEXCOORD _texcoord[0-9]*
+DCL_TANGENT _tangent[0-9]*
+DCL_BINORMAL _binormal[0-9]*
+DCL_TESSFACTOR _tessfactor[0-9]*
+DCL_POSITIONT _positiont[0-9]*
+DCL_COLOR _color[0-9]*
+DCL_FOG _fog[0-9]*
+DCL_DEPTH _depth[0-9]*
+DCL_SAMPLE _sample[0-9]*
+
+DCL_SAMPLER1D _1d
+DCL_SAMPLER2D _2d
+DCL_SAMPLERCUBE _cube
+DCL_SAMPLERVOLUME _volume
+
+PREPROCESSORDIRECTIVE #[^\n]*\n
+
+/* Comments */
+DOUBLESLASHCOMMENT "//"[^\n]*
+SEMICOLONCOMMENT ";"[^\n]*
+
+/* Whitespaces are spaces, tabs and newlines */
+WHITESPACE [ \t]+
+NEWLINE (\n)|(\r\n)
+
+COMMA ","
+
+IMMVAL \-?(([0-9]+)|([0-9]*\.[0-9]+))(f)?
+
+ANY (.)
+
+%%
+
+ /* Common instructions(vertex and pixel shaders) */
+add {return INSTR_ADD; }
+nop {return INSTR_NOP; }
+mov {return INSTR_MOV; }
+sub {return INSTR_SUB; }
+mad {return INSTR_MAD; }
+mul {return INSTR_MUL; }
+rcp {return INSTR_RCP; }
+rsq {return INSTR_RSQ; }
+dp3 {return INSTR_DP3; }
+dp4 {return INSTR_DP4; }
+min {return INSTR_MIN; }
+max {return INSTR_MAX; }
+slt {return INSTR_SLT; }
+sge {return INSTR_SGE; }
+abs {return INSTR_ABS; }
+exp {return INSTR_EXP; }
+log {return INSTR_LOG; }
+expp {return INSTR_EXPP; }
+logp {return INSTR_LOGP; }
+dst {return INSTR_DST; }
+lrp {return INSTR_LRP; }
+frc {return INSTR_FRC; }
+pow {return INSTR_POW; }
+crs {return INSTR_CRS; }
+sgn {return INSTR_SGN; }
+nrm {return INSTR_NRM; }
+sincos {return INSTR_SINCOS; }
+m4x4 {return INSTR_M4x4; }
+m4x3 {return INSTR_M4x3; }
+m3x4 {return INSTR_M3x4; }
+m3x3 {return INSTR_M3x3; }
+m3x2 {return INSTR_M3x2; }
+dcl {return INSTR_DCL; }
+def {return INSTR_DEF; }
+defb {return INSTR_DEFB; }
+defi {return INSTR_DEFI; }
+rep {return INSTR_REP; }
+endrep {return INSTR_ENDREP; }
+if {return INSTR_IF; }
+else {return INSTR_ELSE; }
+endif {return INSTR_ENDIF; }
+break {return INSTR_BREAK; }
+breakp {return INSTR_BREAKP; }
+call {return INSTR_CALL; }
+callnz {return INSTR_CALLNZ; }
+loop {return INSTR_LOOP; }
+ret {return INSTR_RET; }
+endloop {return INSTR_ENDLOOP; }
+label {return INSTR_LABEL; }
+setp {return INSTR_SETP; }
+texldl {return INSTR_TEXLDL; }
+
+ /* Vertex shader only instructions */
+lit {return INSTR_LIT; }
+mova {return INSTR_MOVA; }
+
+ /* Pixel shader only instructions */
+cnd {return INSTR_CND; }
+cmp {return INSTR_CMP; }
+dp2add {return INSTR_DP2ADD; }
+texcoord {return INSTR_TEXCOORD; }
+texcrd {return INSTR_TEXCRD; }
+texkill {return INSTR_TEXKILL; }
+tex {return INSTR_TEX; }
+texld {return INSTR_TEXLD; }
+texbem {return INSTR_TEXBEM; }
+texbeml {return INSTR_TEXBEML; }
+texreg2ar {return INSTR_TEXREG2AR; }
+texreg2gb {return INSTR_TEXREG2GB; }
+texreg2rgb {return INSTR_TEXREG2RGB; }
+texm3x2pad {return INSTR_TEXM3x2PAD; }
+texm3x2tex {return INSTR_TEXM3x2TEX; }
+texm3x3pad {return INSTR_TEXM3x3PAD; }
+texm3x3diff {return INSTR_TEXM3x3DIFF; }
+texm3x3spec {return INSTR_TEXM3x3SPEC; }
+texm3x3vspec {return INSTR_TEXM3x3VSPEC; }
+texm3x3tex {return INSTR_TEXM3x3TEX; }
+texdp3tex {return INSTR_TEXDP3TEX; }
+texm3x2depth {return INSTR_TEXM3x2DEPTH; }
+texdp3 {return INSTR_TEXDP3; }
+texm3x3 {return INSTR_TEXM3x3; }
+texdepth {return INSTR_TEXDEPTH; }
+bem {return INSTR_BEM; }
+dsx {return INSTR_DSX; }
+dsy {return INSTR_DSY; }
+texldp {return INSTR_TEXLDP; }
+texldb {return INSTR_TEXLDB; }
+texldd {return INSTR_TEXLDD; }
+phase {return INSTR_PHASE; }
+
+{REG_TEMP} {
+ yylval->regnum = atoi(yytext + 1);
+ return REG_TEMP;
+ }
+{REG_OUTPUT} {
+ yylval->regnum = atoi(yytext + 1);
+ return REG_OUTPUT;
+ }
+{REG_INPUT} {
+ yylval->regnum = atoi(yytext + 1);
+ return REG_INPUT;
+ }
+{REG_CONSTFLOAT} {
+ yylval->regnum = atoi(yytext + 1);
+ return REG_CONSTFLOAT;
+ }
+{REG_CONSTINT} {
+ yylval->regnum = atoi(yytext + 1);
+ return REG_CONSTINT;
+ }
+{REG_CONSTBOOL} {
+ yylval->regnum = atoi(yytext + 1);
+ return REG_CONSTBOOL;
+ }
+{REG_TEXTURE} {
+ yylval->regnum = atoi(yytext + 1);
+ return REG_TEXTURE;
+ }
+{REG_TEXCRDOUT} {
+ yylval->regnum = atoi(yytext + 2);
+ return REG_TEXCRDOUT;
+ }
+{REG_SAMPLER} {
+ yylval->regnum = atoi(yytext + 1);
+ return REG_SAMPLER;
+ }
+{REG_OPOS} {return REG_OPOS; }
+{REG_OFOG} {return REG_OFOG; }
+{REG_OPTS} {return REG_OPTS; }
+{REG_VERTEXCOLOR} {
+ yylval->regnum = atoi(yytext + 2);
+ return REG_VERTEXCOLOR;
+ }
+{REG_FRAGCOLOR} {
+ yylval->regnum = atoi(yytext + 2);
+ return REG_FRAGCOLOR;
+ }
+{REG_FRAGDEPTH} {
+ return REG_FRAGDEPTH;
+ }
+{REG_VPOS} {return REG_VPOS; }
+{REG_VFACE} {return REG_VFACE; }
+{REG_ADDRESS} {return REG_ADDRESS; }
+{REG_LOOP} {return REG_LOOP; }
+{REG_PREDICATE} {return REG_PREDICATE; }
+
+{REG_LABEL} {
+ yylval->regnum = atoi(yytext + 1);
+ return REG_LABEL;
+ }
+
+ /* Shader versions. These are important to select the correct
+ * parser profile.
+ */
+vs\.1\.0|vs_1_0 {return VER_VS10; }
+vs\.1\.1|vs_1_1 {return VER_VS11; }
+
+vs_2_0 {return VER_VS20; }
+vs_2_x {return VER_VS2X; }
+vs_3_0 {return VER_VS30; }
+
+ps\.1\.0|ps_1_0 {return VER_PS10; }
+ps\.1\.1|ps_1_1 {return VER_PS11; }
+ps\.1\.2|ps_1_2 {return VER_PS12; }
+ps\.1\.3|ps_1_3 {return VER_PS13; }
+ps\.1\.4|ps_1_4 {return VER_PS14; }
+
+ps_2_0 {return VER_PS20; }
+ps_2_x {return VER_PS2X; }
+ps_3_0 {return VER_PS30; }
+
+{SWIZZLE} {
+ unsigned char i;
+ char last = 0;
+ DWORD ret = 0;
+ BOOL wmask_valid = TRUE;
+
+ yylval->swizzle_wmask.swizzle = text2swizzle(yytext + 1);
+ if(yylval->swizzle_wmask.swizzle == SWIZZLE_ERR) {
+ TRACE("Invalid swizzle/writemask %s\n", yytext);
+ yylval->swizzle_wmask.writemask = 0;
+ return SWIZZLE;
+ }
+ ret = 0;
+ last = 0;
+ for(i = 0; i < strlen(yytext + 1); i++) {
+ switch(yytext[i + 1]) {
+ case 'x': case 'X':
+ case 'r': case 'R':
+ if(last == 'x' || last == 'y' || last == 'z' || last == 'w') {
+ wmask_valid = FALSE;
+ break;
+ }
+ ret |= BWRITERSP_WRITEMASK_0;
+ last = 'x';
+ break;
+ case 'y': case 'Y':
+ case 'g': case 'G':
+ if(last == 'y' || last == 'z' || last == 'w') {
+ wmask_valid = FALSE;
+ break;
+ }
+ ret |= BWRITERSP_WRITEMASK_1;
+ last = 'y';
+ break;
+ case 'z': case 'Z':
+ case 'b': case 'B':
+ if(last == 'z' || last == 'w') {
+ wmask_valid = FALSE;
+ break;
+ }
+ ret |= BWRITERSP_WRITEMASK_2;
+ last = 'z';
+ break;
+ case 'w': case 'W':
+ case 'a': case 'A':
+ if(last == 'w') {
+ wmask_valid = FALSE;
+ break;
+ }
+ ret |= BWRITERSP_WRITEMASK_3;
+ last = 'w';
+ break;
+ }
+ }
+ if(wmask_valid) {
+ TRACE("Swizzle/Writemask string is a valid writemask\n");
+ yylval->swizzle_wmask.writemask = ret;
+ } else {
+ TRACE("Swizzle/Writemask string is not a valid writemask\n");
+ yylval->swizzle_wmask.writemask = 0;
+ }
+ return SWIZZLE;
+ }
+
+ /* Output modifiers */
+\_x2 {return SHIFT_X2; }
+\_x4 {return SHIFT_X4; }
+\_x8 {return SHIFT_X8; }
+\_d2 {return SHIFT_D2; }
+\_d4 {return SHIFT_D4; }
+\_d8 {return SHIFT_D8; }
+\_sat {return MOD_SAT; }
+\_pp {return MOD_PP; }
+\_centroid {return MOD_CENTROID; }
+
+ /* compare params */
+\_gt {return COMP_GT; }
+\_lt {return COMP_LT; }
+\_ge {return COMP_GE; }
+\_le {return COMP_LE; }
+\_eq {return COMP_EQ; }
+\_ne {return COMP_NE; }
+
+{IMMVAL} {
+ yylval->immval.val = atof(yytext);
+ yylval->immval.integer = ((strstr(yytext, ".") == NULL) && (strstr(yytext, "f") == NULL));
+ return IMMVAL;
+ }
+true {
+ yylval->immbool = TRUE;
+ return MYBOOL;
+ }
+false {
+ yylval->immbool = FALSE;
+ return MYBOOL;
+ }
+
+{COMMA} {return yytext[0]; }
+- {return yytext[0]; }
+\( {return yytext[0]; }
+\) {return yytext[0]; }
+
+ /* for relative addressing */
+\[|\]|\+ {return yytext[0]; }
+
+\_bias {return SMOD_BIAS; }
+ /* No _x2 here; it is identical to MOD_X2 */
+\_bx2 {return SMOD_SCALEBIAS; }
+\_dz {return SMOD_DZ; }
+\_dw {return SMOD_DW; }
+\_abs {return SMOD_ABS; }
+
+! {return SMOD_NOT; }
+
+{DCL_POSITION} {
+ if(yytext[strlen("_position")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_position"));
+ }
+ return USAGE_POSITION;
+ }
+{DCL_BLENDWEIGHT} {
+ if(yytext[strlen("_blendweight")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_blendweight"));
+ }
+ return USAGE_BLENDWEIGHT;
+ }
+{DCL_BLENDINDICES} {
+ if(yytext[strlen("_blendindices")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_blendindices"));
+ }
+ return USAGE_BLENDINDICES;
+ }
+{DCL_NORMAL} {
+ if(yytext[strlen("_normal")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_normal"));
+ }
+ return USAGE_NORMAL;
+ }
+{DCL_PSIZE} {
+ if(yytext[strlen("_psize")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_psize"));
+ }
+ return USAGE_PSIZE;
+ }
+{DCL_TEXCOORD} {
+ if(yytext[strlen("_texcoord")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_texcoord"));
+ }
+ return USAGE_TEXCOORD;
+ }
+{DCL_TANGENT} {
+ if(yytext[strlen("_tangent")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_tangent"));
+ }
+ return USAGE_TANGENT;
+ }
+{DCL_BINORMAL} {
+ if(yytext[strlen("_binormal")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_binormal"));
+ }
+ return USAGE_BINORMAL;
+ }
+{DCL_TESSFACTOR} {
+ if(yytext[strlen("_tessfactor")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_tessfactor"));
+ }
+ return USAGE_TESSFACTOR;
+ }
+{DCL_POSITIONT} {
+ if(yytext[strlen("_positiont")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_positiont"));
+ }
+ return USAGE_POSITIONT;
+ }
+{DCL_COLOR} {
+ if(yytext[strlen("_color")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_color"));
+ }
+ return USAGE_COLOR;
+ }
+{DCL_FOG} {
+ if(yytext[strlen("_fog")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_fog"));
+ }
+ return USAGE_FOG;
+ }
+{DCL_DEPTH} {
+ if(yytext[strlen("_depth")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_depth"));
+ }
+ return USAGE_DEPTH;
+ }
+{DCL_SAMPLE} {
+ if(yytext[strlen("_sample")] == '\0') {
+ yylval->regnum = 0;
+ } else {
+ yylval->regnum = atoi(yytext + strlen("_sample"));
+ }
+ return USAGE_SAMPLE;
+ }
+
+{DCL_SAMPLER1D} { return SAMPTYPE_1D; }
+{DCL_SAMPLER2D} { return SAMPTYPE_2D; }
+{DCL_SAMPLERCUBE} { return SAMPTYPE_CUBE; }
+{DCL_SAMPLERVOLUME} { return SAMPTYPE_VOLUME; }
+
+{PREPROCESSORDIRECTIVE} {
+ /* TODO: update current line information */
+ TRACE("line info update: %s", yytext);
+ }
+
+ /* Skip comments */
+{DOUBLESLASHCOMMENT} { }
+{SEMICOLONCOMMENT} { }
+
+{WHITESPACE} { /* Do nothing */ }
+{NEWLINE} {
+ struct asm_parser *ctx = yyget_extra(yyscanner);
+ ctx->line_no++;
+ }
+
+{ANY} {
+ struct asm_parser *ctx = yyget_extra(yyscanner);
+ asmparser_message(ctx, "Line %u: Unexpected input %s\n", ctx->line_no, yytext);
+ set_parse_status(ctx, PARSE_ERR);
+ }
+
+%%
+
+struct bwriter_shader *SlAssembleShader(const char *text, char **messages) {
+ struct asm_parser asm_ctx;
+ struct bwriter_shader *ret = NULL;
+ YY_BUFFER_STATE buffer;
+ TRACE("%p, %p\n", text, messages);
+
+ asmshader_lex_init(&asm_ctx.yyscanner);
+ asmshader_set_extra(&asm_ctx, asm_ctx.yyscanner);
+ buffer = asmshader__scan_string(text, asm_ctx.yyscanner);
+ asmshader__switch_to_buffer(buffer, asm_ctx.yyscanner);
+
+ ret = parse_asm_shader(&asm_ctx, messages);
+
+ asmshader__delete_buffer(buffer, asm_ctx.yyscanner);
+ asmshader_lex_destroy(asm_ctx.yyscanner);
+
+ return ret;
+}
diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y
new file mode 100644
index 0000000..6e2f78e
--- /dev/null
+++ b/dlls/d3dx9_36/asmshader.y
@@ -0,0 +1,1606 @@
+/*
+ * Direct3D shader assembler
+ *
+ * Copyright 2008 Stefan Dösinger
+ * Copyright 2009 Matteo Bruni
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+%{
+#include "config.h"
+#include "wine/port.h"
+#include "wine/debug.h"
+
+#include "d3dx9_36_private.h"
+#include "asmshader.tab.h"
+
+#include <stdio.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
+
+/* Needed lexer functions declarations */
+void asmshader_error (struct asm_parser *ctx, void *scanner, char const *s);
+int asmshader_lex (YYSTYPE * yylval_param, void *scanner);
+
+void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
+ /* We can have an additional offset without true relative addressing
+ * ex. c2[ 4 ] */
+ reg->regnum += rel->additional_offset;
+ if(!rel->has_rel_reg) {
+ reg->rel_reg = NULL;
+ } else {
+ reg->rel_reg = asm_alloc(sizeof(*reg->rel_reg));
+ if(!reg->rel_reg) {
+ return;
+ }
+ reg->rel_reg->type = rel->type;
+ reg->rel_reg->swizzle = rel->swizzle;
+ reg->rel_reg->regnum = rel->rel_regnum;
+ }
+}
+
+%}
+
+%pure-parser
+%parse-param{struct asm_parser *ctx}
+%parse-param{void *scanner}
+%lex-param{yyscan_t *scanner}
+
+%union {
+ struct {
+ float val;
+ BOOL integer;
+ } immval;
+ BOOL immbool;
+ unsigned int regnum;
+ struct shader_reg reg;
+ DWORD srcmod;
+ struct {
+ DWORD swizzle;
+ DWORD writemask;
+ } swizzle_wmask;
+ DWORD writemask;
+ DWORD swizzle;
+ struct {
+ DWORD mod;
+ DWORD shift;
+ } modshift;
+ BWRITER_COMPARISON_TYPE comptype;
+ struct {
+ DWORD dclusage;
+ unsigned int regnum;
+ } declaration;
+ BWRITERSAMPLER_TEXTURE_TYPE samplertype;
+ struct rel_reg rel_reg;
+ struct src_regs sregs;
+}
+
+/* Common instructions between vertex and pixel shaders */
+%token INSTR_ADD
+%token INSTR_NOP
+%token INSTR_MOV
+%token INSTR_SUB
+%token INSTR_MAD
+%token INSTR_MUL
+%token INSTR_RCP
+%token INSTR_RSQ
+%token INSTR_DP3
+%token INSTR_DP4
+%token INSTR_MIN
+%token INSTR_MAX
+%token INSTR_SLT
+%token INSTR_SGE
+%token INSTR_ABS
+%token INSTR_EXP
+%token INSTR_LOG
+%token INSTR_EXPP
+%token INSTR_LOGP
+%token INSTR_DST
+%token INSTR_LRP
+%token INSTR_FRC
+%token INSTR_POW
+%token INSTR_CRS
+%token INSTR_SGN
+%token INSTR_NRM
+%token INSTR_SINCOS
+%token INSTR_M4x4
+%token INSTR_M4x3
+%token INSTR_M3x4
+%token INSTR_M3x3
+%token INSTR_M3x2
+%token INSTR_DCL
+%token INSTR_DEF
+%token INSTR_DEFB
+%token INSTR_DEFI
+%token INSTR_REP
+%token INSTR_ENDREP
+%token INSTR_IF
+%token INSTR_ELSE
+%token INSTR_ENDIF
+%token INSTR_BREAK
+%token INSTR_BREAKP
+%token INSTR_CALL
+%token INSTR_CALLNZ
+%token INSTR_LOOP
+%token INSTR_RET
+%token INSTR_ENDLOOP
+%token INSTR_LABEL
+%token INSTR_SETP
+%token INSTR_TEXLDL
+
+/* Vertex shader only instructions */
+%token INSTR_LIT
+%token INSTR_MOVA
+
+/* Pixel shader only instructions */
+%token INSTR_CND
+%token INSTR_CMP
+%token INSTR_DP2ADD
+%token INSTR_TEXCOORD
+%token INSTR_TEXCRD
+%token INSTR_TEXKILL
+%token INSTR_TEX
+%token INSTR_TEXLD
+%token INSTR_TEXBEM
+%token INSTR_TEXBEML
+%token INSTR_TEXREG2AR
+%token INSTR_TEXREG2GB
+%token INSTR_TEXREG2RGB
+%token INSTR_TEXM3x2PAD
+%token INSTR_TEXM3x2TEX
+%token INSTR_TEXM3x3PAD
+%token INSTR_TEXM3x3DIFF
+%token INSTR_TEXM3x3SPEC
+%token INSTR_TEXM3x3VSPEC
+%token INSTR_TEXM3x3TEX
+%token INSTR_TEXDP3TEX
+%token INSTR_TEXM3x2DEPTH
+%token INSTR_TEXDP3
+%token INSTR_TEXM3x3
+%token INSTR_TEXDEPTH
+%token INSTR_BEM
+%token INSTR_DSX
+%token INSTR_DSY
+%token INSTR_TEXLDP
+%token INSTR_TEXLDB
+%token INSTR_TEXLDD
+%token INSTR_PHASE
+
+/* Registers */
+%token <regnum> REG_TEMP
+%token <regnum> REG_OUTPUT
+%token <regnum> REG_INPUT
+%token <regnum> REG_CONSTFLOAT
+%token <regnum> REG_CONSTINT
+%token <regnum> REG_CONSTBOOL
+%token <regnum> REG_TEXTURE
+%token <regnum> REG_SAMPLER
+%token <regnum> REG_TEXCRDOUT
+%token REG_OPOS
+%token REG_OFOG
+%token REG_OPTS
+%token <regnum> REG_VERTEXCOLOR
+%token <regnum> REG_FRAGCOLOR
+%token REG_FRAGDEPTH
+%token REG_VPOS
+%token REG_VFACE
+%token REG_ADDRESS
+%token REG_LOOP
+%token REG_PREDICATE
+%token <regnum> REG_LABEL
+
+/* Version tokens */
+%token VER_VS10
+%token VER_VS11
+%token VER_VS20
+%token VER_VS2X
+%token VER_VS30
+
+%token VER_PS10
+%token VER_PS11
+%token VER_PS12
+%token VER_PS13
+%token VER_PS14
+%token VER_PS20
+%token VER_PS2X
+%token VER_PS30
+
+/* Output modifiers */
+%token SHIFT_X2
+%token SHIFT_X4
+%token SHIFT_X8
+%token SHIFT_D2
+%token SHIFT_D4
+%token SHIFT_D8
+%token MOD_SAT
+%token MOD_PP
+%token MOD_CENTROID
+
+/* Compare tokens */
+%token COMP_GT
+%token COMP_LT
+%token COMP_GE
+%token COMP_LE
+%token COMP_EQ
+%token COMP_NE
+
+/* Source register modifiers */
+%token SMOD_BIAS
+%token SMOD_SCALEBIAS
+%token SMOD_DZ
+%token SMOD_DW
+%token SMOD_ABS
+%token SMOD_NOT
+
+/* Sampler types */
+%token SAMPTYPE_1D
+%token SAMPTYPE_2D
+%token SAMPTYPE_CUBE
+%token SAMPTYPE_VOLUME
+
+/* Usage declaration tokens */
+%token <regnum> USAGE_POSITION
+%token <regnum> USAGE_BLENDWEIGHT
+%token <regnum> USAGE_BLENDINDICES
+%token <regnum> USAGE_NORMAL
+%token <regnum> USAGE_PSIZE
+%token <regnum> USAGE_TEXCOORD
+%token <regnum> USAGE_TANGENT
+%token <regnum> USAGE_BINORMAL
+%token <regnum> USAGE_TESSFACTOR
+%token <regnum> USAGE_POSITIONT
+%token <regnum> USAGE_COLOR
+%token <regnum> USAGE_FOG
+%token <regnum> USAGE_DEPTH
+%token <regnum> USAGE_SAMPLE
+
+/* Misc stuff */
+%token <immval> IMMVAL
+%token <immbool> MYBOOL
+%token <swizzle_wmask> SWIZZLE
+
+%type <reg> dreg_name
+%type <reg> dreg
+%type <reg> sreg_name
+%type <reg> relreg_name
+%type <reg> sreg
+%type <srcmod> smod
+%type <swizzle> swizzle
+%type <writemask> writemask
+%type <modshift> omods
+%type <modshift> omodifier
+%type <comptype> comp
+%type <declaration> dclusage
+%type <samplertype> sampdcl
+%type <rel_reg> rel_reg
+%type <reg> predicate
+%type <immval> immsum
+%type <sregs> sregs
+
+%%
+
+shader: version_marker instructions
+ {
+ ctx->funcs->end(ctx);
+ }
+
+version_marker: VER_VS10
+ {
+ TRACE("Vertex shader 1.0\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_VS11
+ {
+ TRACE("Vertex shader 1.1\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_VS20
+ {
+ TRACE("Vertex shader 2.0\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_VS2X
+ {
+ TRACE("Vertex shader 2.x\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_VS30
+ {
+ TRACE("Vertex shader 3.0\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_PS10
+ {
+ TRACE("Pixel shader 1.0\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_PS11
+ {
+ TRACE("Pixel shader 1.1\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_PS12
+ {
+ TRACE("Pixel shader 1.2\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_PS13
+ {
+ TRACE("Pixel shader 1.3\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_PS14
+ {
+ TRACE("Pixel shader 1.4\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_PS20
+ {
+ TRACE("Pixel shader 2.0\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_PS2X
+ {
+ TRACE("Pixel shader 2.x\n");
+ /* TODO: create the appropriate parser context */
+ }
+ | VER_PS30
+ {
+ TRACE("Pixel shader 3.0\n");
+ /* TODO: create the appropriate parser context */
+ }
+
+instructions: /* empty */
+ | instructions complexinstr
+ {
+ /* Nothing to do */
+ }
+
+complexinstr: instruction
+ {
+
+ }
+ | predicate instruction
+ {
+ TRACE("predicate\n");
+ ctx->funcs->predicate(ctx, &$1);
+ }
+ | '+' instruction
+ {
+ TRACE("coissue\n");
+ ctx->funcs->coissue(ctx);
+ }
+
+instruction: INSTR_ADD omods dreg ',' sregs
+ {
+ TRACE("ADD\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_ADD, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_NOP
+ {
+ TRACE("NOP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_NOP, 0, 0, 0, 0, 0, 0);
+ }
+ | INSTR_MOV omods dreg ',' sregs
+ {
+ TRACE("MOV\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_MOV, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_SUB omods dreg ',' sregs
+ {
+ TRACE("SUB\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_SUB, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_MAD omods dreg ',' sregs
+ {
+ TRACE("MAD\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_MAD, $2.mod, $2.shift, 0, &$3, &$5, 3);
+ }
+ | INSTR_MUL omods dreg ',' sregs
+ {
+ TRACE("MUL\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_MUL, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_RCP omods dreg ',' sregs
+ {
+ TRACE("RCP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_RCP, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_RSQ omods dreg ',' sregs
+ {
+ TRACE("RSQ\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_RSQ, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_DP3 omods dreg ',' sregs
+ {
+ TRACE("DP3\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_DP3, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_DP4 omods dreg ',' sregs
+ {
+ TRACE("DP4\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_DP4, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_MIN omods dreg ',' sregs
+ {
+ TRACE("MIN\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_MIN, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_MAX omods dreg ',' sregs
+ {
+ TRACE("MAX\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_MAX, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_SLT omods dreg ',' sregs
+ {
+ TRACE("SLT\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_SLT, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_SGE omods dreg ',' sregs
+ {
+ TRACE("SGE\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_SGE, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_ABS omods dreg ',' sregs
+ {
+ TRACE("ABS\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_ABS, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_EXP omods dreg ',' sregs
+ {
+ TRACE("EXP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_EXP, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_LOG omods dreg ',' sregs
+ {
+ TRACE("LOG\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_LOG, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_LOGP omods dreg ',' sregs
+ {
+ TRACE("LOGP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_LOGP, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_EXPP omods dreg ',' sregs
+ {
+ TRACE("EXPP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_EXPP, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_DST omods dreg ',' sregs
+ {
+ TRACE("DST\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_DST, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_LRP omods dreg ',' sregs
+ {
+ TRACE("LRP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_LRP, $2.mod, $2.shift, 0, &$3, &$5, 3);
+ }
+ | INSTR_FRC omods dreg ',' sregs
+ {
+ TRACE("FRC\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_FRC, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_POW omods dreg ',' sregs
+ {
+ TRACE("POW\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_POW, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_CRS omods dreg ',' sregs
+ {
+ TRACE("CRS\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_CRS, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_SGN omods dreg ',' sregs
+ {
+ TRACE("SGN\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_SGN, $2.mod, $2.shift, 0, &$3, &$5, 3);
+ }
+ | INSTR_NRM omods dreg ',' sregs
+ {
+ TRACE("NRM\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_NRM, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_SINCOS omods dreg ',' sregs
+ {
+ TRACE("SINCOS\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_SINCOS, $2.mod, $2.shift, 0, &$3, &$5, 3);
+ }
+ | INSTR_M4x4 omods dreg ',' sregs
+ {
+ TRACE("M4x4\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_M4x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_M4x3 omods dreg ',' sregs
+ {
+ TRACE("M4x3\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_M4x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_M3x4 omods dreg ',' sregs
+ {
+ TRACE("M3x4\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_M3x4, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_M3x3 omods dreg ',' sregs
+ {
+ TRACE("M3x3\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_M3x3, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_M3x2 omods dreg ',' sregs
+ {
+ TRACE("M3x2\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_M3x2, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_DCL dclusage REG_OUTPUT
+ {
+ struct shader_reg reg;
+ TRACE("Output reg declaration\n");
+ memset(®, 0, sizeof(reg));
+ reg.type = BWRITERSPR_OUTPUT;
+ reg.regnum = $3;
+ reg.rel_reg = NULL;
+ reg.srcmod = 0;
+ reg.writemask = BWRITERSP_WRITEMASK_ALL;
+ ctx->funcs->dcl_output(ctx, $2.dclusage, $2.regnum, ®);
+ }
+ | INSTR_DCL dclusage REG_OUTPUT writemask
+ {
+ struct shader_reg reg;
+ TRACE("Output reg declaration\n");
+ memset(®, 0, sizeof(reg));
+ reg.type = BWRITERSPR_OUTPUT;
+ reg.regnum = $3;
+ reg.rel_reg = NULL;
+ reg.srcmod = 0;
+ reg.writemask = $4;
+ ctx->funcs->dcl_output(ctx, $2.dclusage, $2.regnum, ®);
+ }
+ | INSTR_DCL dclusage REG_INPUT
+ {
+ struct shader_reg reg;
+ TRACE("Input reg declaration\n");
+ memset(®, 0, sizeof(reg));
+ reg.type = BWRITERSPR_INPUT;
+ reg.regnum = $3;
+ reg.rel_reg = NULL;
+ reg.srcmod = 0;
+ reg.writemask = BWRITERSP_WRITEMASK_ALL;
+ ctx->funcs->dcl_input(ctx, $2.dclusage, $2.regnum, ®);
+ }
+ | INSTR_DCL dclusage REG_INPUT writemask
+ {
+ struct shader_reg reg;
+ TRACE("Input reg declaration\n");
+ memset(®, 0, sizeof(reg));
+ reg.type = BWRITERSPR_INPUT;
+ reg.regnum = $3;
+ reg.rel_reg = NULL;
+ reg.srcmod = 0;
+ reg.writemask = $4;
+ ctx->funcs->dcl_input(ctx, $2.dclusage, $2.regnum, ®);
+ }
+ | INSTR_DCL sampdcl REG_SAMPLER
+ {
+ TRACE("Sampler declared\n");
+ ctx->funcs->dcl_sampler(ctx, $2, $3, ctx->line_no);
+ }
+ | INSTR_DCL sampdcl REG_INPUT
+ {
+ TRACE("Error rule: sampler decl of input reg\n");
+ asmparser_message(ctx, "Line %u: Sampler declarations of input regs is not valid\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | INSTR_DCL sampdcl REG_OUTPUT
+ {
+ TRACE("Error rule: sampler decl of output reg\n");
+ asmparser_message(ctx, "Line %u: Sampler declarations of output regs is not valid\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | INSTR_DEF REG_CONSTFLOAT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
+ {
+ ctx->funcs->constF(ctx, $2, $4.val, $6.val, $8.val, $10.val);
+ }
+ | INSTR_DEFI REG_CONSTINT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL
+ {
+ ctx->funcs->constI(ctx, $2, $4.val, $6.val, $8.val, $10.val);
+ }
+ | INSTR_DEFB REG_CONSTBOOL ',' MYBOOL
+ {
+ ctx->funcs->constB(ctx, $2, $4);
+ }
+ | INSTR_REP sregs
+ {
+ TRACE("REP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_REP, 0, 0, 0, 0, &$2, 1);
+ }
+ | INSTR_ENDREP
+ {
+ TRACE("ENDREP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_ENDREP, 0, 0, 0, 0, 0, 0);
+ }
+ | INSTR_IF sregs
+ {
+ TRACE("IF\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_IF, 0, 0, 0, 0, &$2, 1);
+ }
+ | INSTR_IF comp sregs
+ {
+ TRACE("IFC\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_IFC, 0, 0, $2, 0, &$3, 2);
+ }
+ | INSTR_ELSE
+ {
+ TRACE("ELSE\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_ELSE, 0, 0, 0, 0, 0, 0);
+ }
+ | INSTR_ENDIF
+ {
+ TRACE("ENDIF\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_ENDIF, 0, 0, 0, 0, 0, 0);
+ }
+ | INSTR_BREAK
+ {
+ TRACE("BREAK\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_BREAK, 0, 0, 0, 0, 0, 0);
+ }
+ | INSTR_BREAK comp sregs
+ {
+ TRACE("BREAKC\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_BREAKC, 0, 0, $2, 0, &$3, 2);
+ }
+ | INSTR_BREAKP sregs
+ {
+ TRACE("BREAKP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_BREAKP, 0, 0, 0, 0, &$2, 1);
+ }
+ | INSTR_CALL sregs
+ {
+ TRACE("CALL\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_CALL, 0, 0, 0, 0, &$2, 1);
+ }
+ | INSTR_CALLNZ sregs
+ {
+ TRACE("CALLNZ\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_CALLNZ, 0, 0, 0, 0, &$2, 2);
+ }
+ | INSTR_LOOP sregs
+ {
+ TRACE("LOOP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_LOOP, 0, 0, 0, 0, &$2, 2);
+ }
+ | INSTR_RET
+ {
+ TRACE("RET\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_RET, 0, 0, 0, 0, 0, 0);
+ }
+ | INSTR_ENDLOOP
+ {
+ TRACE("ENDLOOP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_ENDLOOP, 0, 0, 0, 0, 0, 0);
+ }
+ | INSTR_LABEL sregs
+ {
+ TRACE("LABEL\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_LABEL, 0, 0, 0, 0, &$2, 1);
+ }
+ | INSTR_SETP comp dreg ',' sregs
+ {
+ TRACE("SETP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_SETP, 0, 0, $2, &$3, &$5, 2);
+ }
+ | INSTR_TEXLDL omods dreg ',' sregs
+ {
+ TRACE("TEXLDL\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXLDL, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_LIT omods dreg ',' sregs
+ {
+ TRACE("LIT\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_LIT, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_MOVA dreg ',' sregs
+ {
+ TRACE("MOVA\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_MOVA, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_CND omods dreg ',' sregs
+ {
+ TRACE("CND\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_CND, $2.mod, $2.shift, 0, &$3, &$5, 3);
+ }
+ | INSTR_CMP omods dreg ',' sregs
+ {
+ TRACE("CMP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_CMP, $2.mod, $2.shift, 0, &$3, &$5, 3);
+ }
+ | INSTR_DP2ADD omods dreg ',' sregs
+ {
+ TRACE("DP2ADD\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_DP2ADD, $2.mod, $2.shift, 0, &$3, &$5, 3);
+ }
+ | INSTR_TEXCOORD dreg
+ {
+ TRACE("TEXCOORD\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXCOORD, 0, 0, 0, &$2, 0, 0);
+ }
+ | INSTR_TEXCRD omods dreg ',' sregs
+ {
+ TRACE("TEXCRD\n");
+ /* texcoord and texcrd share the same opcode */
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXCOORD, $2.mod, $2.shift, 0, &$3, &$5, 1);
+ }
+ | INSTR_TEXKILL dreg
+ {
+ TRACE("TEXKILL\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXKILL, 0, 0, 0, &$2, 0, 0);
+ }
+ | INSTR_TEX dreg
+ {
+ TRACE("TEX\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEX, 0, 0, 0, &$2, 0, 0);
+ }
+ | INSTR_TEXDEPTH dreg
+ {
+ TRACE("TEXDEPTH\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXDEPTH, 0, 0, 0, &$2, 0, 0);
+ }
+ | INSTR_TEXLD omods dreg ',' sregs
+ {
+ TRACE("TEXLD\n");
+ /* There is more than one acceptable syntax for texld:
+ with 1 sreg (PS 1.4) or
+ with 2 sregs (PS 2.0+)
+ Moreover, texld shares the same opcode as the tex instruction,
+ so there are a total of 3 valid syntaxes
+ These variations are handled in asmparser.c */
+ ctx->funcs->instr(ctx, BWRITERSIO_TEX, $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_TEXLDP omods dreg ',' sregs
+ {
+ TRACE("TEXLDP\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEX | ( BWRITERSI_TEXLD_PROJECT << BWRITER_OPCODESPECIFICCONTROL_SHIFT ), $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_TEXLDB omods dreg ',' sregs
+ {
+ TRACE("TEXLDB\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEX | ( BWRITERSI_TEXLD_BIAS << BWRITER_OPCODESPECIFICCONTROL_SHIFT ), $2.mod, $2.shift, 0, &$3, &$5, 2);
+ }
+ | INSTR_TEXBEM dreg ',' sregs
+ {
+ TRACE("TEXBEM\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXBEM, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXBEML dreg ',' sregs
+ {
+ TRACE("TEXBEML\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXBEML, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXREG2AR dreg ',' sregs
+ {
+ TRACE("TEXREG2AR\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXREG2AR, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXREG2GB dreg ',' sregs
+ {
+ TRACE("TEXREG2GB\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXREG2GB, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXREG2RGB dreg ',' sregs
+ {
+ TRACE("TEXREG2RGB\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXREG2RGB, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXM3x2PAD dreg ',' sregs
+ {
+ TRACE("TEXM3x2PAD\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXM3x2PAD, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXM3x3PAD dreg ',' sregs
+ {
+ TRACE("INSTR_TEXM3x3PAD\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXM3x3PAD, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXM3x3DIFF dreg ',' sregs /* ??? That one's in wined3d but not the sdk */
+ {
+ ERR("INSTR_TEXM3x3DIFF\n");
+ }
+ | INSTR_TEXM3x3SPEC dreg ',' sregs
+ {
+ TRACE("TEXM3x3SPEC\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXM3x3SPEC, 0, 0, 0, &$2, &$4, 2);
+ }
+ | INSTR_TEXM3x3VSPEC dreg ',' sregs
+ {
+ TRACE("TEXM3x3VSPEC\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXM3x3VSPEC, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXM3x3TEX dreg ',' sregs
+ {
+ TRACE("TEXM3x3TEX\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXM3x3TEX, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXDP3TEX dreg ',' sregs
+ {
+ TRACE("TEXDP3TEX\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXDP3TEX, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXM3x2DEPTH dreg ',' sregs
+ {
+ TRACE("TEXM3x2DEPTH\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXM3x2DEPTH, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXM3x2TEX dreg ',' sregs
+ {
+ TRACE("TEXM3x2TEX\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXM3x2TEX, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXDP3 dreg ',' sregs
+ {
+ TRACE("TEXDP3\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXDP3, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXM3x3 dreg ',' sregs
+ {
+ TRACE("TEXM3x3\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXM3x3, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_BEM dreg ',' sregs
+ {
+ TRACE("BEM\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_BEM, 0, 0, 0, &$2, &$4, 2);
+ }
+ | INSTR_DSX dreg ',' sregs
+ {
+ TRACE("DSX\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_DSX, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_DSY dreg ',' sregs
+ {
+ TRACE("DSY\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_DSY, 0, 0, 0, &$2, &$4, 1);
+ }
+ | INSTR_TEXLDD dreg ',' sregs
+ {
+ TRACE("TEXLDD\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_TEXLDD, 0, 0, 0, &$2, &$4, 4);
+ }
+ | INSTR_PHASE
+ {
+ TRACE("PHASE\n");
+ ctx->funcs->instr(ctx, BWRITERSIO_PHASE, 0, 0, 0, 0, 0, 0);
+ }
+
+
+dreg: dreg_name rel_reg
+ {
+ $$.regnum = $1.regnum;
+ $$.type = $1.type;
+ $$.writemask = BWRITERSP_WRITEMASK_ALL;
+ $$.srcmod = BWRITERSPSM_NONE;
+ set_rel_reg(&$$, &$2);
+ }
+ | dreg_name writemask
+ {
+ $$.regnum = $1.regnum;
+ $$.type = $1.type;
+ $$.writemask = $2;
+ $$.srcmod = BWRITERSPSM_NONE;
+ $$.rel_reg = NULL;
+ }
+
+dreg_name: REG_TEMP
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
+ }
+ | REG_OUTPUT
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_OUTPUT;
+ }
+ | REG_INPUT
+ {
+ asmparser_message(ctx, "Line %u: Register v%u is not a valid destination register\n",
+ ctx->line_no, $1);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_CONSTFLOAT
+ {
+ asmparser_message(ctx, "Line %u: Register c%u is not a valid destination register\n",
+ ctx->line_no, $1);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_CONSTINT
+ {
+ asmparser_message(ctx, "Line %u: Register i%u is not a valid destination register\n",
+ ctx->line_no, $1);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_CONSTBOOL
+ {
+ asmparser_message(ctx, "Line %u: Register b%u is not a valid destination register\n",
+ ctx->line_no, $1);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_TEXTURE
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
+ }
+ | REG_TEXCRDOUT
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_TEXCRDOUT;
+ }
+ | REG_SAMPLER
+ {
+ asmparser_message(ctx, "Line %u: Register s%u is not a valid destination register\n",
+ ctx->line_no, $1);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_OPOS
+ {
+ $$.regnum = BWRITERSRO_POSITION ; $$.type = BWRITERSPR_RASTOUT;
+ }
+ | REG_OPTS
+ {
+ $$.regnum = BWRITERSRO_POINT_SIZE ; $$.type = BWRITERSPR_RASTOUT;
+ }
+ | REG_OFOG
+ {
+ $$.regnum = BWRITERSRO_FOG ; $$.type = BWRITERSPR_RASTOUT;
+ }
+ | REG_VERTEXCOLOR
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_ATTROUT;
+ }
+ | REG_FRAGCOLOR
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_COLOROUT;
+ }
+ | REG_FRAGDEPTH
+ {
+ $$.regnum = 0; $$.type = BWRITERSPR_DEPTHOUT;
+ }
+ | REG_PREDICATE
+ {
+ $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
+ }
+ | REG_VPOS
+ {
+ asmparser_message(ctx, "Line %u: Register vPos is not a valid destination register\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_VFACE
+ {
+ asmparser_message(ctx, "Line %u: Register vFace is not a valid destination register\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_ADDRESS
+ {
+ /* index 0 is hardcoded for the addr register */
+ $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
+ }
+ | REG_LOOP
+ {
+ asmparser_message(ctx, "Line %u: Register aL is not a valid destination register\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+
+writemask: SWIZZLE
+ {
+ TRACE("Got a writemask\n");
+ if($1.writemask == 0) {
+ asmparser_message(ctx, "Line %u: Invalid writemask specified\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_ERR);
+ /* Provide a correct writemask to prevent follow-up complaints */
+ $$ = BWRITERSP_WRITEMASK_ALL;
+ } else {
+ $$ = $1.writemask;
+ }
+ }
+
+swizzle: /* empty */
+ {
+ $$ = BWRITERVS_NOSWIZZLE;
+ TRACE("Default swizzle: %08x\n", $$);
+ }
+ | SWIZZLE
+ {
+ if($1.swizzle == SWIZZLE_ERR) {
+ asmparser_message(ctx, "Line %u: Invalid swizzle\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_ERR);
+ /* Provide a correct swizzle to prevent follow-up complaints */
+ $$ = BWRITERSP_NOSWIZZLE;
+ }
+ else {
+ TRACE("Got a swizzle: %08x\n", $1.swizzle);
+ $$ = $1.swizzle;
+ }
+ }
+
+omods: /* Empty */
+ {
+ $$.mod = 0;
+ $$.shift = 0;
+ }
+ | omods omodifier
+ {
+ $$.mod = $1.mod | $2.mod;
+ if($1.shift && $2.shift) {
+ asmparser_message(ctx, "Line %u: More than one shift flag\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_ERR);
+ $$.shift = $1.shift;
+ } else {
+ $$.shift = $1.shift | $2.shift;
+ }
+ }
+
+omodifier: SHIFT_X2
+ {
+ $$.mod = 0;
+ $$.shift = 1;
+ }
+ | SHIFT_X4
+ {
+ $$.mod = 0;
+ $$.shift = 2;
+ }
+ | SHIFT_X8
+ {
+ $$.mod = 0;
+ $$.shift = 3;
+ }
+ | SHIFT_D2
+ {
+ $$.mod = 0;
+ $$.shift = 15;
+ }
+ | SHIFT_D4
+ {
+ $$.mod = 0;
+ $$.shift = 14;
+ }
+ | SHIFT_D8
+ {
+ $$.mod = 0;
+ $$.shift = 13;
+ }
+ | MOD_SAT
+ {
+ $$.mod = BWRITERSPDM_SATURATE;
+ $$.shift = 0;
+ }
+ | MOD_PP
+ {
+ $$.mod = BWRITERSPDM_PARTIALPRECISION;
+ $$.shift = 0;
+ }
+ | MOD_CENTROID
+ {
+ $$.mod = BWRITERSPDM_MSAMPCENTROID;
+ $$.shift = 0;
+ }
+
+sregs: sreg
+ {
+ $$.reg[0] = $1;
+ $$.count = 1;
+ }
+ | sregs ',' sreg
+ {
+ if($$.count == MAX_SRC_REGS){
+ asmparser_message(ctx, "Line %u: Too many source registers in this instruction\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_ERR);
+ }
+ else
+ $$.reg[$$.count++] = $3;
+ }
+
+sreg: sreg_name rel_reg swizzle
+ {
+ $$.type = $1.type;
+ $$.regnum = $1.regnum;
+ $$.swizzle = $3;
+ $$.srcmod = BWRITERSPSM_NONE;
+ set_rel_reg(&$$, &$2);
+ }
+ | sreg_name rel_reg smod swizzle
+ {
+ $$.type = $1.type;
+ $$.regnum = $1.regnum;
+ set_rel_reg(&$$, &$2);
+ $$.srcmod = $3;
+ $$.swizzle = $4;
+ }
+ | '-' sreg_name rel_reg swizzle
+ {
+ $$.type = $2.type;
+ $$.regnum = $2.regnum;
+ $$.srcmod = BWRITERSPSM_NEG;
+ set_rel_reg(&$$, &$3);
+ $$.swizzle = $4;
+ }
+ | '-' sreg_name rel_reg smod swizzle
+ {
+ $$.type = $2.type;
+ $$.regnum = $2.regnum;
+ set_rel_reg(&$$, &$3);
+ switch($4) {
+ case BWRITERSPSM_BIAS: $$.srcmod = BWRITERSPSM_BIASNEG; break;
+ case BWRITERSPSM_X2: $$.srcmod = BWRITERSPSM_X2NEG; break;
+ case BWRITERSPSM_SIGN: $$.srcmod = BWRITERSPSM_SIGNNEG; break;
+ case BWRITERSPSM_ABS: $$.srcmod = BWRITERSPSM_ABSNEG; break;
+ case BWRITERSPSM_DZ:
+ asmparser_message(ctx, "Line %u: Incompatible source modifiers: NEG and DZ\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_ERR);
+ break;
+ case BWRITERSPSM_DW:
+ asmparser_message(ctx, "Line %u: Incompatible source modifiers: NEG and DW\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_ERR);
+ break;
+ default:
+ FIXME("Unhandled combination of NEGATE and %u\n", $4);
+ }
+ $$.swizzle = $5;
+ }
+ | IMMVAL '-' sreg_name rel_reg swizzle
+ {
+ if($1.val != 1.0 || (!$1.integer)) {
+ asmparser_message(ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP, "
+ "%g - reg found\n", ctx->line_no, $1.val);
+ set_parse_status(ctx, PARSE_ERR);
+ }
+ /* Complement - not compatible with other source modifiers */
+ $$.type = $3.type;
+ $$.regnum = $3.regnum;
+ $$.srcmod = BWRITERSPSM_COMP;
+ set_rel_reg(&$$, &$4);
+ $$.swizzle = $5;
+ }
+ | IMMVAL '-' sreg_name rel_reg smod swizzle
+ {
+ /* For nicer error reporting */
+ if($1.val != 1.0 || (!$1.integer)) {
+ asmparser_message(ctx, "Line %u: Only \"1 - reg\" is valid for D3DSPSM_COMP\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_ERR);
+ } else {
+ asmparser_message(ctx, "Line %u: Incompatible source modifiers: D3DSPSM_COMP and %s\n",
+ ctx->line_no,
+ debug_print_srcmod($5));
+ set_parse_status(ctx, PARSE_ERR);
+ }
+ }
+ | SMOD_NOT sreg_name swizzle
+ {
+ $$.type = $2.type;
+ $$.regnum = $2.regnum;
+ $$.rel_reg = NULL;
+ $$.srcmod = BWRITERSPSM_NOT;
+ $$.swizzle = $3;
+ }
+
+rel_reg: /* empty */
+ {
+ $$.has_rel_reg = FALSE;
+ $$.additional_offset = 0;
+ }
+ | '[' immsum ']'
+ {
+ $$.has_rel_reg = FALSE;
+ $$.additional_offset = $2.val;
+ }
+ | '[' relreg_name swizzle ']'
+ {
+ $$.has_rel_reg = TRUE;
+ $$.type = $2.type;
+ $$.additional_offset = 0;
+ $$.rel_regnum = $2.regnum;
+ $$.swizzle = $3;
+ }
+ | '[' immsum '+' relreg_name swizzle ']'
+ {
+ $$.has_rel_reg = TRUE;
+ $$.type = $4.type;
+ $$.additional_offset = $2.val;
+ $$.rel_regnum = $4.regnum;
+ $$.swizzle = $5;
+ }
+ | '[' relreg_name swizzle '+' immsum ']'
+ {
+ $$.has_rel_reg = TRUE;
+ $$.type = $2.type;
+ $$.additional_offset = $5.val;
+ $$.rel_regnum = $2.regnum;
+ $$.swizzle = $3;
+ }
+ | '[' immsum '+' relreg_name swizzle '+' immsum ']'
+ {
+ $$.has_rel_reg = TRUE;
+ $$.type = $4.type;
+ $$.additional_offset = $2.val + $7.val;
+ $$.rel_regnum = $4.regnum;
+ $$.swizzle = $5;
+ }
+
+immsum: IMMVAL
+ {
+ if(!$1.integer) {
+ asmparser_message(ctx, "Line %u: Unexpected float %f\n",
+ ctx->line_no, $1.val);
+ set_parse_status(ctx, PARSE_ERR);
+ }
+ $$.val = $1.val;
+ }
+ | immsum '+' IMMVAL
+ {
+ if(!$3.integer) {
+ asmparser_message(ctx, "Line %u: Unexpected float %f\n",
+ ctx->line_no, $3.val);
+ set_parse_status(ctx, PARSE_ERR);
+ }
+ $$.val = $1.val + $3.val;
+ }
+
+smod: SMOD_BIAS
+ {
+ $$ = BWRITERSPSM_BIAS;
+ }
+ | SHIFT_X2
+ {
+ $$ = BWRITERSPSM_X2;
+ }
+ | SMOD_SCALEBIAS
+ {
+ $$ = BWRITERSPSM_SIGN;
+ }
+ | SMOD_DZ
+ {
+ $$ = BWRITERSPSM_DZ;
+ }
+ | SMOD_DW
+ {
+ $$ = BWRITERSPSM_DW;
+ }
+ | SMOD_ABS
+ {
+ $$ = BWRITERSPSM_ABS;
+ }
+
+relreg_name: REG_ADDRESS
+ {
+ $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
+ }
+ | REG_LOOP
+ {
+ $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
+ }
+
+sreg_name: REG_TEMP
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
+ }
+ | REG_OUTPUT
+ {
+ asmparser_message(ctx, "Line %u: Register o%u is not a valid source register\n",
+ ctx->line_no, $1);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_INPUT
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_INPUT;
+ }
+ | REG_CONSTFLOAT
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_CONST;
+ }
+ | REG_CONSTINT
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_CONSTINT;
+ }
+ | REG_CONSTBOOL
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_CONSTBOOL;
+ }
+ | REG_TEXTURE
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_TEXTURE;
+ }
+ | REG_TEXCRDOUT
+ {
+ asmparser_message(ctx, "Line %u: Register oT%u is not a valid source register\n",
+ ctx->line_no, $1);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_SAMPLER
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_SAMPLER;
+ }
+ | REG_OPOS
+ {
+ asmparser_message(ctx, "Line %u: Register oPos is not a valid source register\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_OFOG
+ {
+ asmparser_message(ctx, "Line %u: Register oFog is not a valid source register\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_VERTEXCOLOR
+ {
+ asmparser_message(ctx, "Line %u: Register oD%u is not a valid source register\n",
+ ctx->line_no, $1);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_FRAGCOLOR
+ {
+ asmparser_message(ctx, "Line %u: Register oC%u is not a valid source register\n",
+ ctx->line_no, $1);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_FRAGDEPTH
+ {
+ asmparser_message(ctx, "Line %u: Register oDepth is not a valid source register\n",
+ ctx->line_no);
+ set_parse_status(ctx, PARSE_WARN);
+ }
+ | REG_PREDICATE
+ {
+ $$.regnum = 0; $$.type = BWRITERSPR_PREDICATE;
+ }
+ | REG_VPOS
+ {
+ /* No constants defined for this ? */
+ $$.regnum = 0; $$.type = BWRITERSPR_MISCTYPE;
+ }
+ | REG_VFACE
+ {
+ /* No constants defined for this ? */
+ $$.regnum = 1; $$.type = BWRITERSPR_MISCTYPE;
+ }
+ | REG_ADDRESS
+ {
+ $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
+ }
+ | REG_LOOP
+ {
+ $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
+ }
+ | REG_LABEL
+ {
+ $$.regnum = $1; $$.type = BWRITERSPR_LABEL;
+ }
+ | IMMVAL { FIXME("Immediate src argument\n"); }
+
+comp: COMP_GT { $$ = BWRITER_COMPARISON_GT; }
+ | COMP_LT { $$ = BWRITER_COMPARISON_LT; }
+ | COMP_GE { $$ = BWRITER_COMPARISON_GE; }
+ | COMP_LE { $$ = BWRITER_COMPARISON_LE; }
+ | COMP_EQ { $$ = BWRITER_COMPARISON_EQ; }
+ | COMP_NE { $$ = BWRITER_COMPARISON_NE; }
+
+dclusage: USAGE_POSITION
+ {
+ TRACE("dcl_position%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_POSITION;
+ }
+ | USAGE_BLENDWEIGHT
+ {
+ TRACE("dcl_blendweight%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_BLENDWEIGHT;
+ }
+ | USAGE_BLENDINDICES
+ {
+ TRACE("dcl_blendindices%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_BLENDINDICES;
+ }
+ | USAGE_NORMAL
+ {
+ TRACE("dcl_normal%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_NORMAL;
+ }
+ | USAGE_PSIZE
+ {
+ TRACE("dcl_psize%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_PSIZE;
+ }
+ | USAGE_TEXCOORD
+ {
+ TRACE("dcl_texcoord%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_TEXCOORD;
+ }
+ | USAGE_TANGENT
+ {
+ TRACE("dcl_tangent%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_TANGENT;
+ }
+ | USAGE_BINORMAL
+ {
+ TRACE("dcl_binormal%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_BINORMAL;
+ }
+ | USAGE_TESSFACTOR
+ {
+ TRACE("dcl_tessfactor%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_TESSFACTOR;
+ }
+ | USAGE_POSITIONT
+ {
+ TRACE("dcl_positiont%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_POSITIONT;
+ }
+ | USAGE_COLOR
+ {
+ TRACE("dcl_color%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_COLOR;
+ }
+ | USAGE_FOG
+ {
+ TRACE("dcl_fog%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_FOG;
+ }
+ | USAGE_DEPTH
+ {
+ TRACE("dcl_depth%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_DEPTH;
+ }
+ | USAGE_SAMPLE
+ {
+ TRACE("dcl_sample%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_SAMPLE;
+ }
+
+sampdcl: SAMPTYPE_1D
+ {
+ $$ = BWRITERSTT_1D;
+ }
+ | SAMPTYPE_2D
+ {
+ $$ = BWRITERSTT_2D;
+ }
+ | SAMPTYPE_CUBE
+ {
+ $$ = BWRITERSTT_CUBE;
+ }
+ | SAMPTYPE_VOLUME
+ {
+ $$ = BWRITERSTT_VOLUME;
+ }
+
+predicate: '(' REG_PREDICATE swizzle ')'
+ {
+ $$.type = BWRITERSPR_PREDICATE;
+ $$.regnum = 0;
+ $$.rel_reg = NULL;
+ $$.srcmod = BWRITERSPSM_NONE;
+ $$.swizzle = $3;
+ }
+ | '(' SMOD_NOT REG_PREDICATE swizzle ')'
+ {
+ $$.type = BWRITERSPR_PREDICATE;
+ $$.regnum = 0;
+ $$.rel_reg = NULL;
+ $$.srcmod = BWRITERSPSM_NOT;
+ $$.swizzle = $4;
+ }
+
+%%
+
+void asmshader_error (struct asm_parser *ctx, void *scanner, char const *s) {
+ asmparser_message(ctx, "Line %u: Error \"%s\" from bison\n", ctx->line_no, s);
+ set_parse_status(ctx, PARSE_ERR);
+}
+
+/* Error reporting function */
+void asmparser_message(struct asm_parser *ctx, const char *fmt, ...) {
+ va_list args;
+ char* newbuffer;
+ int rc, newsize;
+
+ if(ctx->messagecapacity == 0) {
+ ctx->messages = asm_alloc(MESSAGEBUFFER_INITIAL_SIZE);
+ if(ctx->messages == NULL) {
+ ERR("Error allocating memory for parser messages\n");
+ return;
+ }
+ ctx->messagecapacity = MESSAGEBUFFER_INITIAL_SIZE;
+ }
+
+ while(1) {
+ va_start(args, fmt);
+ rc = vsnprintf(ctx->messages + ctx->messagesize,
+ ctx->messagecapacity - ctx->messagesize, fmt, args);
+ va_end(args);
+
+ if (rc < 0 || /* C89 */
+ rc >= ctx->messagecapacity - ctx->messagesize) { /* C99 */
+ /* Resize the buffer */
+ newsize = ctx->messagecapacity * 2;
+ newbuffer = asm_realloc(ctx->messages, newsize);
+ if(newbuffer == NULL){
+ ERR("Error reallocating memory for parser messages\n");
+ return;
+ }
+ ctx->messages = newbuffer;
+ ctx->messagecapacity = newsize;
+ } else {
+ ctx->messagesize += rc;
+ return;
+ }
+ }
+}
+
+/* new status is the worse between current status and parameter value */
+void set_parse_status(struct asm_parser *ctx, enum parse_status status) {
+ if(status == PARSE_ERR) ctx->status = PARSE_ERR;
+ else if(status == PARSE_WARN && ctx->status == PARSE_SUCCESS) ctx->status = PARSE_WARN;
+}
+
+struct bwriter_shader *parse_asm_shader(struct asm_parser *asm_ctx, char **messages) {
+ struct bwriter_shader *ret = NULL;
+
+ asm_ctx->shader = NULL;
+ asm_ctx->status = PARSE_SUCCESS;
+ asm_ctx->messagesize = asm_ctx->messagecapacity = 0;
+ asm_ctx->line_no = 1;
+
+ asmshader_parse(asm_ctx, asm_ctx->yyscanner);
+
+ if(asm_ctx->status != PARSE_ERR) ret = asm_ctx->shader;
+ else if(asm_ctx->shader) SlDeleteShader(asm_ctx->shader);
+
+ if(messages) {
+ if(asm_ctx->messagesize) {
+ /* Shrink the buffer to the used size */
+ *messages = asm_realloc(asm_ctx->messages, asm_ctx->messagesize + 1);
+ if(!*messages) {
+ ERR("Out of memory, no messages reported\n");
+ asm_free(asm_ctx->messages);
+ }
+ } else {
+ *messages = NULL;
+ }
+ }
+ else{
+ if(asm_ctx->messagecapacity) asm_free(asm_ctx->messages);
+ }
+
+ return ret;
+}
--
1.6.3.3
More information about the wine-patches
mailing list