/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2006 Torus Knot Software Ltd Also see acknowledgements in Readme.html This program 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 of the License, or (at your option) any later version. This program 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 program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. You may alternatively use this source under the terms of a specific version of the OGRE Unrestricted License provided you have obtained such a license from Torus Knot Software Ltd. ----------------------------------------------------------------------------- */ //--------------------------------------------------------------------------- #include "ps_1_4.h" //--------------------------------------------------------------------------- /* ********************* START OF PS_1_4 CLASS STATIC DATA ********************************* */ // library of built in symbol types bool PS_1_4::LibInitialized = false; #define SYMSTART { #define SYMDEF ,0,0,0,0},{ #define SYMEND ,0,0,0,0} PS_1_4::SymbolDef PS_1_4::PS_1_4_SymbolTypeLib[] = { // pixel shader versions supported { sid_PS_1_4, GL_NONE, ckp_PS_BASE, ckp_PS_1_4, 0, 0, 0 }, { sid_PS_1_1, GL_NONE, ckp_PS_BASE, ckp_PS_1_1, 0, 0, 0 }, { sid_PS_1_2, GL_NONE, ckp_PS_BASE, ckp_PS_1_2 + ckp_PS_1_1, 0, 0, 0 }, { sid_PS_1_3, GL_NONE, ckp_PS_BASE, ckp_PS_1_3 + ckp_PS_1_2 + ckp_PS_1_1, 0, 0, 0 }, // PS_BASE // constants SYMSTART sid_C0, GL_CON_0_ATI, ckp_PS_BASE SYMDEF sid_C1, GL_CON_1_ATI, ckp_PS_BASE SYMDEF sid_C2, GL_CON_2_ATI, ckp_PS_BASE SYMDEF sid_C3, GL_CON_3_ATI, ckp_PS_BASE SYMDEF sid_C4, GL_CON_4_ATI, ckp_PS_BASE SYMDEF sid_C5, GL_CON_5_ATI, ckp_PS_BASE SYMDEF sid_C6, GL_CON_6_ATI, ckp_PS_BASE SYMDEF sid_C7, GL_CON_7_ATI, ckp_PS_BASE // colour SYMDEF sid_V0, GL_PRIMARY_COLOR_ARB, ckp_PS_BASE SYMDEF sid_V1, GL_SECONDARY_INTERPOLATOR_ATI, ckp_PS_BASE // instruction ops SYMDEF sid_ADD, GL_ADD_ATI, ckp_PS_BASE SYMDEF sid_SUB, GL_SUB_ATI, ckp_PS_BASE SYMDEF sid_MUL, GL_MUL_ATI, ckp_PS_BASE SYMDEF sid_MAD, GL_MAD_ATI, ckp_PS_BASE SYMDEF sid_LRP, GL_LERP_ATI, ckp_PS_BASE SYMDEF sid_MOV, GL_MOV_ATI, ckp_PS_BASE SYMDEF sid_CMP, GL_CND0_ATI, ckp_PS_BASE SYMDEF sid_CND, GL_CND_ATI, ckp_PS_BASE SYMDEF sid_DP3, GL_DOT3_ATI, ckp_PS_BASE SYMDEF sid_DP4, GL_DOT4_ATI, ckp_PS_BASE SYMDEF sid_DEF, GL_NONE, ckp_PS_BASE // Masks SYMDEF sid_R, GL_RED_BIT_ATI, ckp_PS_1_4 SYMDEF sid_RA, GL_RED_BIT_ATI | ALPHA_BIT, ckp_PS_1_4 SYMDEF sid_G, GL_GREEN_BIT_ATI, ckp_PS_1_4 SYMDEF sid_GA, GL_GREEN_BIT_ATI | ALPHA_BIT, ckp_PS_1_4 SYMDEF sid_B, GL_BLUE_BIT_ATI, ckp_PS_1_4 SYMDEF sid_BA, GL_BLUE_BIT_ATI | ALPHA_BIT, ckp_PS_1_4 SYMDEF sid_A, ALPHA_BIT, ckp_PS_BASE SYMDEF sid_RGBA, RGB_BITS | ALPHA_BIT, ckp_PS_BASE SYMDEF sid_RGB, RGB_BITS, ckp_PS_BASE SYMDEF sid_RG, GL_RED_BIT_ATI | GL_GREEN_BIT_ATI, ckp_PS_1_4 SYMDEF sid_RGA, GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | ALPHA_BIT, ckp_PS_1_4 SYMDEF sid_RB, GL_RED_BIT_ATI | GL_BLUE_BIT_ATI, ckp_PS_1_4 SYMDEF sid_RBA, GL_RED_BIT_ATI | GL_BLUE_BIT_ATI | ALPHA_BIT, ckp_PS_1_4 SYMDEF sid_GB, GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI, ckp_PS_1_4 SYMDEF sid_GBA, GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI | ALPHA_BIT, ckp_PS_1_4 // Rep SYMDEF sid_RRRR, GL_RED, ckp_PS_1_4 SYMDEF sid_GGGG, GL_GREEN, ckp_PS_1_4 SYMDEF sid_BBBB, GL_BLUE, ckp_PS_BASE SYMDEF sid_AAAA, GL_ALPHA, ckp_PS_BASE // modifiers SYMDEF sid_X2, GL_2X_BIT_ATI, ckp_PS_BASE SYMDEF sid_X4, GL_4X_BIT_ATI, ckp_PS_BASE SYMDEF sid_D2, GL_HALF_BIT_ATI, ckp_PS_BASE SYMDEF sid_SAT, GL_SATURATE_BIT_ATI, ckp_PS_BASE // argument modifiers SYMDEF sid_BIAS, GL_BIAS_BIT_ATI, ckp_PS_BASE SYMDEF sid_INVERT, GL_COMP_BIT_ATI, ckp_PS_BASE SYMDEF sid_NEGATE, GL_NEGATE_BIT_ATI, ckp_PS_BASE SYMDEF sid_BX2, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI, ckp_PS_BASE // seperator characters SYMDEF sid_COMMA, GL_NONE, ckp_PS_BASE SYMDEF sid_VALUE, GL_NONE, ckp_PS_BASE // PS_1_4 // temp R/W registers SYMDEF sid_R0, GL_REG_0_ATI, ckp_PS_1_4 SYMDEF sid_R1, GL_REG_1_ATI, ckp_PS_1_4 SYMDEF sid_R2, GL_REG_2_ATI, ckp_PS_1_4 SYMDEF sid_R3, GL_REG_3_ATI, ckp_PS_1_4 SYMDEF sid_R4, GL_REG_4_ATI, ckp_PS_1_4 SYMDEF sid_R5, GL_REG_5_ATI, ckp_PS_1_4 // textures SYMDEF sid_T0, GL_TEXTURE0_ARB, ckp_PS_1_4 SYMDEF sid_T1, GL_TEXTURE1_ARB, ckp_PS_1_4 SYMDEF sid_T2, GL_TEXTURE2_ARB, ckp_PS_1_4 SYMDEF sid_T3, GL_TEXTURE3_ARB, ckp_PS_1_4 SYMDEF sid_T4, GL_TEXTURE4_ARB, ckp_PS_1_4 SYMDEF sid_T5, GL_TEXTURE5_ARB, ckp_PS_1_4 SYMDEF sid_DP2ADD, GL_DOT2_ADD_ATI, ckp_PS_1_4 // modifiers SYMDEF sid_X8, GL_8X_BIT_ATI, ckp_PS_1_4 SYMDEF sid_D8, GL_EIGHTH_BIT_ATI, ckp_PS_1_4 SYMDEF sid_D4, GL_QUARTER_BIT_ATI, ckp_PS_1_4 // instructions SYMDEF sid_TEXCRD, GL_NONE, ckp_PS_1_4 SYMDEF sid_TEXLD, GL_NONE, ckp_PS_1_4 // texture swizzlers SYMDEF sid_STR, GL_SWIZZLE_STR_ATI - GL_SWIZZLE_STR_ATI, ckp_PS_1_4 SYMDEF sid_STQ, GL_SWIZZLE_STQ_ATI - GL_SWIZZLE_STR_ATI, ckp_PS_1_4 SYMDEF sid_STRDR, GL_SWIZZLE_STR_DR_ATI - GL_SWIZZLE_STR_ATI, ckp_PS_1_4 SYMDEF sid_STQDQ, GL_SWIZZLE_STQ_DQ_ATI - GL_SWIZZLE_STR_ATI, ckp_PS_1_4 SYMDEF sid_BEM, GL_NONE, ckp_PS_1_4 SYMDEF sid_PHASE, GL_NONE, ckp_PS_1_4 // PS_1_1 // temp R/W registers // r0, r1 are mapped to r4, r5 // t0 to t3 are mapped to r0 to r3 SYMDEF sid_1R0, GL_REG_4_ATI, ckp_PS_1_1 SYMDEF sid_1R1, GL_REG_5_ATI, ckp_PS_1_1 SYMDEF sid_1T0, GL_REG_0_ATI, ckp_PS_1_1 SYMDEF sid_1T1, GL_REG_1_ATI, ckp_PS_1_1 SYMDEF sid_1T2, GL_REG_2_ATI, ckp_PS_1_1 SYMDEF sid_1T3, GL_REG_3_ATI, ckp_PS_1_1 // instructions common to PS_1_1, PS_1_2, PS_1_3 SYMDEF sid_TEX, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXCOORD, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXM3X2PAD, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXM3X2TEX, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXM3X3PAD, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXM3X3TEX, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXM3X3SPEC, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXM3X3VSPEC, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXREG2AR, GL_NONE, ckp_PS_1_2 SYMDEF sid_TEXREG2GB, GL_NONE, ckp_PS_1_2 // PS_1_2 & PS_1_3 SYMDEF sid_TEXREG2RGB, GL_NONE, ckp_PS_1_2 SYMDEF sid_TEXDP3, GL_NONE, ckp_PS_1_2 SYMDEF sid_TEXDP3TEX, GL_NONE, ckp_PS_1_2 // Common SYMDEF sid_SKIP, GL_NONE, ckp_PS_BASE SYMDEF sid_PLUS, GL_NONE, ckp_PS_BASE // Non-Terminal Tokens SYMDEF sid_PROGRAM, GL_NONE, ckp_PS_BASE SYMDEF sid_PROGRAMTYPE, GL_NONE, ckp_PS_BASE SYMDEF sid_DECLCONSTS, GL_NONE, ckp_PS_BASE SYMDEF sid_DEFCONST, GL_NONE, ckp_PS_BASE SYMDEF sid_CONSTANT, GL_NONE, ckp_PS_BASE SYMDEF sid_COLOR, GL_NONE, ckp_PS_BASE SYMDEF sid_TEXSWIZZLE, GL_NONE, ckp_PS_BASE SYMDEF sid_UNARYOP, GL_NONE, ckp_PS_BASE SYMDEF sid_NUMVAL, GL_NONE, ckp_PS_BASE SYMDEF sid_SEPERATOR, GL_NONE, ckp_PS_BASE SYMDEF sid_ALUOPS, GL_NONE, ckp_PS_BASE SYMDEF sid_TEXMASK, GL_NONE, ckp_PS_BASE SYMDEF sid_TEXOP_PS1_1_3, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXOP_PS1_4, GL_NONE, ckp_PS_1_4 SYMDEF sid_ALU_STATEMENT, GL_NONE, ckp_PS_BASE SYMDEF sid_DSTMODSAT, GL_NONE, ckp_PS_BASE SYMDEF sid_UNARYOP_ARGS, GL_NONE, ckp_PS_BASE SYMDEF sid_REG_PS1_4, GL_NONE, ckp_PS_1_4 SYMDEF sid_TEX_PS1_4, GL_NONE, ckp_PS_1_4 SYMDEF sid_REG_PS1_1_3, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEX_PS1_1_3, GL_NONE, ckp_PS_1_1 SYMDEF sid_DSTINFO, GL_NONE, ckp_PS_BASE SYMDEF sid_SRCINFO, GL_NONE, ckp_PS_BASE SYMDEF sid_BINARYOP_ARGS, GL_NONE, ckp_PS_BASE SYMDEF sid_TERNARYOP_ARGS, GL_NONE, ckp_PS_BASE SYMDEF sid_TEMPREG, GL_NONE, ckp_PS_BASE SYMDEF sid_DSTMASK, GL_NONE, ckp_PS_BASE SYMDEF sid_PRESRCMOD, GL_NONE, ckp_PS_BASE SYMDEF sid_SRCNAME, GL_NONE, ckp_PS_BASE SYMDEF sid_SRCREP, GL_NONE, ckp_PS_BASE SYMDEF sid_POSTSRCMOD, GL_NONE, ckp_PS_BASE SYMDEF sid_DSTMOD, GL_NONE, ckp_PS_BASE SYMDEF sid_DSTSAT, GL_NONE, ckp_PS_BASE SYMDEF sid_BINARYOP, GL_NONE, ckp_PS_BASE SYMDEF sid_TERNARYOP, GL_NONE, ckp_PS_BASE SYMDEF sid_TEXOPS_PHASE1, GL_NONE, ckp_PS_BASE SYMDEF sid_COISSUE, GL_NONE, ckp_PS_BASE SYMDEF sid_PHASEMARKER, GL_NONE, ckp_PS_1_4 SYMDEF sid_TEXOPS_PHASE2, GL_NONE, ckp_PS_1_4 SYMDEF sid_TEXREG_PS1_4, GL_NONE, ckp_PS_1_4 SYMDEF sid_TEXOPS_PS1_4, GL_NONE, ckp_PS_1_4 SYMDEF sid_TEXOPS_PS1_1_3, GL_NONE, ckp_PS_1_1 SYMDEF sid_TEXCISCOP_PS1_1_3, GL_NONE, ckp_PS_1_1 SYMEND }; // Rule Path Database for ps.1.x code based on extended Backus Naur Form notation // <> - non-terminal token #define _rule_ {otRULE, // ::= - rule definition #define _is_ ,0},{otAND, #define _and_ ,0},{otAND, // - blank space is an implied "AND" meaning the token is required #define _or_ ,0},{otOR, // | - or #define _optional_ ,0},{otOPTIONAL, // [] - optional #define _repeat_ ,0},{otREPEAT, // {} - repeat until fail #define _end_ ,0},{otEND,0,0,0}, #define _nt_ ,0 // " " - terminal token string PS_1_4::TokenRule PS_1_4::PS_1_x_RulePath[] = { _rule_ sid_PROGRAM, "Program" _is_ sid_PROGRAMTYPE _nt_ _optional_ sid_DECLCONSTS _nt_ _optional_ sid_TEXOPS_PHASE1 _nt_ _optional_ sid_ALUOPS _nt_ _optional_ sid_PHASEMARKER _nt_ _optional_ sid_TEXOPS_PHASE2 _nt_ _optional_ sid_ALUOPS _nt_ _end_ _rule_ sid_PROGRAMTYPE, "" _is_ sid_PS_1_4, "ps.1.4" _or_ sid_PS_1_1, "ps.1.1" _or_ sid_PS_1_2, "ps.1.2" _or_ sid_PS_1_3, "ps.1.3" _end_ _rule_ sid_PHASEMARKER, "" _is_ sid_PHASE, "phase" _end_ _rule_ sid_DECLCONSTS, "" _repeat_ sid_DEFCONST _nt_ _end_ _rule_ sid_TEXOPS_PHASE1, "" _is_ sid_TEXOPS_PS1_1_3 _nt_ _or_ sid_TEXOPS_PS1_4 _nt_ _end_ _rule_ sid_TEXOPS_PHASE2, "" _is_ sid_TEXOPS_PS1_4 _nt_ _end_ _rule_ sid_NUMVAL, "" _is_ sid_VALUE, "Float Value" _end_ _rule_ sid_TEXOPS_PS1_1_3, "" _repeat_ sid_TEXOP_PS1_1_3 _nt_ _end_ _rule_ sid_TEXOPS_PS1_4, "" _repeat_ sid_TEXOP_PS1_4 _nt_ _end_ _rule_ sid_TEXOP_PS1_1_3, "" _is_ sid_TEXCISCOP_PS1_1_3 _nt_ _and_ sid_TEX_PS1_1_3 _nt_ _and_ sid_SEPERATOR _nt_ _and_ sid_TEX_PS1_1_3 _nt_ _or_ sid_TEXCOORD, "texcoord" _and_ sid_TEX_PS1_1_3 _nt_ _or_ sid_TEX, "tex" _and_ sid_TEX_PS1_1_3 _nt_ _end_ _rule_ sid_TEXOP_PS1_4, "" _is_ sid_TEXCRD, "texcrd" _and_ sid_REG_PS1_4 _nt_ _optional_ sid_TEXMASK _nt_ _and_ sid_SEPERATOR _nt_ _and_ sid_TEXREG_PS1_4 _nt_ _or_ sid_TEXLD, "texld" _and_ sid_REG_PS1_4 _nt_ _optional_ sid_TEXMASK _nt_ _and_ sid_SEPERATOR _nt_ _and_ sid_TEXREG_PS1_4 _nt_ _end_ _rule_ sid_ALUOPS, "" _repeat_ sid_ALU_STATEMENT _nt_ _end_ _rule_ sid_ALU_STATEMENT, "" _is_ sid_COISSUE _nt_ _and_ sid_UNARYOP _nt_ _optional_ sid_DSTMODSAT _nt_ _and_ sid_UNARYOP_ARGS _nt_ _or_ sid_COISSUE _nt_ _and_ sid_BINARYOP _nt_ _optional_ sid_DSTMODSAT _nt_ _and_ sid_BINARYOP_ARGS _nt_ _or_ sid_COISSUE _nt_ _and_ sid_TERNARYOP _nt_ _optional_ sid_DSTMODSAT _nt_ _and_ sid_TERNARYOP_ARGS _nt_ _end_ _rule_ sid_TEXREG_PS1_4, "" _is_ sid_TEX_PS1_4 _nt_ _optional_ sid_TEXSWIZZLE _nt_ _or_ sid_REG_PS1_4 _nt_ _optional_ sid_TEXSWIZZLE _nt_ _end_ _rule_ sid_UNARYOP_ARGS, "" _is_ sid_DSTINFO _nt_ _and_ sid_SRCINFO _nt_ _end_ _rule_ sid_BINARYOP_ARGS, "" _is_ sid_DSTINFO _nt_ _and_ sid_SRCINFO _nt_ _and_ sid_SRCINFO _nt_ _end_ _rule_ sid_TERNARYOP_ARGS, "" _is_ sid_DSTINFO _nt_ _and_ sid_SRCINFO _nt_ _and_ sid_SRCINFO _nt_ _and_ sid_SRCINFO _nt_ _end_ _rule_ sid_DSTINFO, "" _is_ sid_TEMPREG _nt_ _optional_ sid_DSTMASK _nt_ _end_ _rule_ sid_SRCINFO, "" _is_ sid_SEPERATOR _nt_ _optional_ sid_PRESRCMOD _nt_ _and_ sid_SRCNAME _nt_ _optional_ sid_POSTSRCMOD _nt_ _optional_ sid_SRCREP _nt_ _end_ _rule_ sid_SRCNAME, "" _is_ sid_TEMPREG _nt_ _or_ sid_CONSTANT _nt_ _or_ sid_COLOR _nt_ _end_ _rule_ sid_DEFCONST, "" _is_ sid_DEF, "def" _and_ sid_CONSTANT _nt_ _and_ sid_SEPERATOR _nt_ _and_ sid_NUMVAL _nt_ _and_ sid_SEPERATOR _nt_ _and_ sid_NUMVAL _nt_ _and_ sid_SEPERATOR _nt_ _and_ sid_NUMVAL _nt_ _and_ sid_SEPERATOR _nt_ _and_ sid_NUMVAL _nt_ _end_ _rule_ sid_CONSTANT, "" _is_ sid_C0, "c0" _or_ sid_C1, "c1" _or_ sid_C2, "c2" _or_ sid_C3, "c3" _or_ sid_C4, "c4" _or_ sid_C5, "c5" _or_ sid_C6, "c6" _or_ sid_C7, "c7" _end_ _rule_ sid_TEXCISCOP_PS1_1_3, "" _is_ sid_TEXDP3TEX, "texdp3tex" _or_ sid_TEXDP3, "texdp3" _or_ sid_TEXM3X2PAD, "texm3x2pad" _or_ sid_TEXM3X2TEX, "texm3x2tex" _or_ sid_TEXM3X3PAD, "texm3x3pad" _or_ sid_TEXM3X3TEX, "texm3x3tex" _or_ sid_TEXM3X3SPEC, "texm3x3spec" _or_ sid_TEXM3X3VSPEC, "texm3x3vspec" _or_ sid_TEXREG2RGB, "texreg2rgb" _or_ sid_TEXREG2AR, "texreg2ar" _or_ sid_TEXREG2GB, "texreg2gb" _end_ _rule_ sid_TEXSWIZZLE, "" _is_ sid_STQDQ, "_dw.xyw" _or_ sid_STQDQ, "_dw" _or_ sid_STQDQ, "_da.rga" _or_ sid_STQDQ, "_da" _or_ sid_STRDR, "_dz.xyz" _or_ sid_STRDR, "_dz" _or_ sid_STRDR, "_db.rgb" _or_ sid_STRDR, "_db" _or_ sid_STR, ".xyz" _or_ sid_STR, ".rgb" _or_ sid_STQ, ".xyw" _or_ sid_STQ, ".rga" _end_ _rule_ sid_TEXMASK, "" _is_ sid_RGB, ".rgb" _or_ sid_RGB, ".xyz" _or_ sid_RG, ".rg" _or_ sid_RG, ".xy" _end_ _rule_ sid_SEPERATOR, "" _is_ sid_COMMA, "," _end_ _rule_ sid_REG_PS1_4, "" _is_ sid_R0, "r0" _or_ sid_R1, "r1" _or_ sid_R2, "r2" _or_ sid_R3, "r3" _or_ sid_R4, "r4" _or_ sid_R5, "r5" _end_ _rule_ sid_TEX_PS1_4, "" _is_ sid_T0, "t0" _or_ sid_T1, "t1" _or_ sid_T2, "t2" _or_ sid_T3, "t3" _or_ sid_T4, "t4" _or_ sid_T5, "t5" _end_ _rule_ sid_REG_PS1_1_3, "" _is_ sid_1R0, "r0" _or_ sid_1R1, "r1" _end_ _rule_ sid_TEX_PS1_1_3, "" _is_ sid_1T0, "t0" _or_ sid_1T1, "t1" _or_ sid_1T2, "t2" _or_ sid_1T3, "t3" _end_ _rule_ sid_COLOR, "" _is_ sid_V0, "v0" _or_ sid_V1, "v1" _end_ _rule_ sid_TEMPREG, "" _is_ sid_REG_PS1_4 _nt_ _or_ sid_REG_PS1_1_3 _nt_ _or_ sid_TEX_PS1_1_3 _nt_ _end_ _rule_ sid_DSTMODSAT, "" _optional_ sid_DSTMOD _nt_ _optional_ sid_DSTSAT _nt_ _end_ _rule_ sid_UNARYOP, "" _is_ sid_MOV, "mov" _end_ _rule_ sid_BINARYOP, "" _is_ sid_ADD, "add" _or_ sid_MUL, "mul" _or_ sid_SUB, "sub" _or_ sid_DP3, "dp3" _or_ sid_DP4, "dp4" _or_ sid_BEM, "bem" _end_ _rule_ sid_TERNARYOP, "" _is_ sid_MAD, "mad" _or_ sid_LRP, "lrp" _or_ sid_CND, "cnd" _or_ sid_CMP, "cmp" _end_ _rule_ sid_DSTMASK, "" _is_ sid_RGBA, ".rgba" _or_ sid_RGBA, ".xyzw" _or_ sid_RGB, ".rgb" _or_ sid_RGB, ".xyz" _or_ sid_RGA, ".xyw" _or_ sid_RGA, ".rga" _or_ sid_RBA, ".rba" _or_ sid_RBA, ".xzw" _or_ sid_GBA, ".gba" _or_ sid_GBA, ".yzw" _or_ sid_RG, ".rg" _or_ sid_RG, ".xy" _or_ sid_RB, ".xz" _or_ sid_RB, ".rb" _or_ sid_RA, ".xw" _or_ sid_RA, ".ra" _or_ sid_GB, ".gb" _or_ sid_GB, ".yz" _or_ sid_GA, ".yw" _or_ sid_GA, ".ga" _or_ sid_BA, ".zw" _or_ sid_BA, ".ba" _or_ sid_R, ".r" _or_ sid_R, ".x" _or_ sid_G, ".g" _or_ sid_G, ".y" _or_ sid_B, ".b" _or_ sid_B, ".z" _or_ sid_A, ".a" _or_ sid_A, ".w" _end_ _rule_ sid_SRCREP, "" _is_ sid_RRRR, ".r" _or_ sid_RRRR, ".x" _or_ sid_GGGG, ".g" _or_ sid_GGGG, ".y" _or_ sid_BBBB, ".b" _or_ sid_BBBB, ".z" _or_ sid_AAAA, ".a" _or_ sid_AAAA, ".w" _end_ _rule_ sid_PRESRCMOD, "" _is_ sid_INVERT, "1-" _or_ sid_INVERT, "1 -" _or_ sid_NEGATE, "-" _end_ _rule_ sid_POSTSRCMOD, "" _is_ sid_BX2, "_bx2" _or_ sid_X2, "_x2" _or_ sid_BIAS, "_bias" _end_ _rule_ sid_DSTMOD, "" _is_ sid_X2, "_x2" _or_ sid_X4, "_x4" _or_ sid_D2, "_d2" _or_ sid_X8, "_x8" _or_ sid_D4, "_d4" _or_ sid_D8, "_d8" _end_ _rule_ sid_DSTSAT, "" _is_ sid_SAT, "_sat" _end_ _rule_ sid_COISSUE, "" _optional_ sid_PLUS, "+" _end_ }; //***************************** MACROs for PS1_1 , PS1_2, PS1_3 CISC instructions ************************************** // macro to make the macro text data easier to read #define _token_ ,0,0},{ #define _token_end_ ,0,0} // macro token expansion for ps_1_2 instruction: texreg2ar PS_1_4::TokenInst PS_1_4::texreg2ar[] = { // mov r(x).r, r(y).a { sid_UNARYOP, sid_MOV _token_ sid_REG_PS1_4, sid_R1 _token_ sid_DSTMASK, sid_R _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 _token_ sid_SRCREP, sid_AAAA // mov r(x).g, r(y).r _token_ sid_UNARYOP, sid_MOV _token_ sid_REG_PS1_4, sid_R1 _token_ sid_DSTMASK, sid_G _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 _token_ sid_SRCREP, sid_RRRR // texld r(x), r(x) _token_ sid_TEXOP_PS1_4, sid_TEXLD _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R1 _token_end_ }; PS_1_4::RegModOffset PS_1_4::texreg2xx_RegMods[] = { {1, R_BASE, 0}, {7, R_BASE, 0}, {13, R_BASE, 0}, {15, R_BASE, 0}, {4, R_BASE, 1}, {10, R_BASE, 1}, }; PS_1_4::MacroRegModify PS_1_4::texreg2ar_MacroMods = { texreg2ar, ARRAYSIZE(texreg2ar), texreg2xx_RegMods, ARRAYSIZE(texreg2xx_RegMods) }; // macro token expansion for ps_1_2 instruction: texreg2gb PS_1_4::TokenInst PS_1_4::texreg2gb[] = { // mov r(x).r, r(y).g { sid_UNARYOP, sid_MOV _token_ sid_REG_PS1_4, sid_R1 _token_ sid_DSTMASK, sid_R _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 _token_ sid_SRCREP, sid_GGGG // mov r(x).g, r(y).b _token_ sid_UNARYOP, sid_MOV _token_ sid_REG_PS1_4, sid_R1 _token_ sid_DSTMASK, sid_G _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 _token_ sid_SRCREP, sid_BBBB // texld r(x), r(x) _token_ sid_TEXOP_PS1_4, sid_TEXLD _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R1 _token_end_ }; PS_1_4::MacroRegModify PS_1_4::texreg2gb_MacroMods = { texreg2gb, ARRAYSIZE(texreg2gb), texreg2xx_RegMods, ARRAYSIZE(texreg2xx_RegMods) }; // macro token expansion for ps_1_1 instruction: texdp3 PS_1_4::TokenInst PS_1_4::texdp3[] = { // texcoord t(x) { sid_TEXOP_PS1_1_3, sid_TEXCOORD _token_ sid_TEX_PS1_1_3, sid_1T1 // dp3 r(x), r(x), r(y) _token_ sid_BINARYOP, sid_DP3 _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 _token_end_ }; PS_1_4::RegModOffset PS_1_4::texdp3_RegMods[] = { {1, T_BASE, 0}, {3, R_BASE, 0}, {5, R_BASE, 0}, {7, R_BASE, 1}, }; PS_1_4::MacroRegModify PS_1_4::texdp3_MacroMods = { texdp3, ARRAYSIZE(texdp3), texdp3_RegMods, ARRAYSIZE(texdp3_RegMods) }; // macro token expansion for ps_1_1 instruction: texdp3tex PS_1_4::TokenInst PS_1_4::texdp3tex[] = { // texcoord t(x) { sid_TEXOP_PS1_1_3, sid_TEXCOORD _token_ sid_TEX_PS1_1_3, sid_1T1 // dp3 r1, r(x), r(y) _token_ sid_BINARYOP, sid_DP3 _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 // texld r(x), r(x) _token_ sid_TEXOP_PS1_4, sid_TEXLD _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R1 _token_end_ }; PS_1_4::RegModOffset PS_1_4::texdp3tex_RegMods[] = { {1, T_BASE, 0}, {3, R_BASE, 0}, {5, R_BASE, 0}, {7, R_BASE, 1}, {9, R_BASE, 1}, {11, R_BASE, 1}, }; PS_1_4::MacroRegModify PS_1_4::texdp3tex_MacroMods = { texdp3tex, ARRAYSIZE(texdp3tex), texdp3tex_RegMods, ARRAYSIZE(texdp3tex_RegMods) }; // macro token expansion for ps_1_1 instruction: texm3x2pad PS_1_4::TokenInst PS_1_4::texm3x2pad[] = { // texcoord t(x) { sid_TEXOP_PS1_1_3, sid_TEXCOORD _token_ sid_TEX_PS1_1_3, sid_1T0 // dp3 r4.r, r(x), r(y) _token_ sid_BINARYOP, sid_DP3 _token_ sid_REG_PS1_4, sid_R4 _token_ sid_DSTMASK, sid_R _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 _token_end_ }; PS_1_4::RegModOffset PS_1_4::texm3xxpad_RegMods[] = { {1, T_BASE, 0}, {6, R_BASE, 0}, {8, R_BASE, 1}, }; PS_1_4::MacroRegModify PS_1_4::texm3x2pad_MacroMods = { texm3x2pad, ARRAYSIZE(texm3x2pad), texm3xxpad_RegMods, ARRAYSIZE(texm3xxpad_RegMods) }; // macro token expansion for ps_1_1 instruction: texm3x2tex PS_1_4::TokenInst PS_1_4::texm3x2tex[] = { // texcoord t(x) { sid_TEXOP_PS1_1_3, sid_TEXCOORD _token_ sid_TEX_PS1_1_3, sid_1T1 // dp3 r4.g, r(x), r(y) _token_ sid_BINARYOP, sid_DP3 _token_ sid_REG_PS1_4, sid_R4 _token_ sid_DSTMASK, sid_G _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 // texld r(x), r4 _token_ sid_TEXOP_PS1_4, sid_TEXLD _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R4 _token_end_ }; PS_1_4::RegModOffset PS_1_4::texm3xxtex_RegMods[] = { {1, T_BASE, 0}, {6, R_BASE, 0}, {8, R_BASE, 1}, {10, R_BASE, 0} }; PS_1_4::MacroRegModify PS_1_4::texm3x2tex_MacroMods = { texm3x2tex, ARRAYSIZE(texm3x2tex), texm3xxtex_RegMods, ARRAYSIZE(texm3xxtex_RegMods) }; // macro token expansion for ps_1_1 instruction: texm3x3tex PS_1_4::TokenInst PS_1_4::texm3x3pad[] = { // texcoord t(x) { sid_TEXOP_PS1_1_3, sid_TEXCOORD _token_ sid_TEX_PS1_1_3, sid_1T0 // dp3 r4.b, r(x), r(y) _token_ sid_BINARYOP, sid_DP3 _token_ sid_REG_PS1_4, sid_R4 _token_ sid_DSTMASK, sid_B _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 _token_end_ }; PS_1_4::MacroRegModify PS_1_4::texm3x3pad_MacroMods = { texm3x3pad, ARRAYSIZE(texm3x3pad), texm3xxpad_RegMods, ARRAYSIZE(texm3xxpad_RegMods) }; // macro token expansion for ps_1_1 instruction: texm3x3pad PS_1_4::TokenInst PS_1_4::texm3x3tex[] = { // texcoord t(x) { sid_TEXOP_PS1_1_3, sid_TEXCOORD _token_ sid_TEX_PS1_1_3, sid_1T1 // dp3 r4.b, r(x), r(y) _token_ sid_BINARYOP, sid_DP3 _token_ sid_REG_PS1_4, sid_R4 _token_ sid_DSTMASK, sid_B _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 // texld r1, r4 _token_ sid_TEXOP_PS1_4, sid_TEXLD _token_ sid_REG_PS1_4, sid_R1 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R4 _token_end_ }; PS_1_4::MacroRegModify PS_1_4::texm3x3tex_MacroMods = { texm3x3tex, ARRAYSIZE(texm3x3tex), texm3xxtex_RegMods, ARRAYSIZE(texm3xxtex_RegMods) }; // macro token expansion for ps_1_1 instruction: texm3x3spec PS_1_4::TokenInst PS_1_4::texm3x3spec[] = { // texcoord t(x) { sid_TEXOP_PS1_1_3, sid_TEXCOORD _token_ sid_TEX_PS1_1_3, sid_1T3 // dp3 r4.b, r3, r(x) _token_ sid_BINARYOP, sid_DP3 _token_ sid_REG_PS1_4, sid_R4 _token_ sid_DSTMASK, sid_B _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R3 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R0 // dp3_x2 r3, r4, c(x) _token_ sid_BINARYOP, sid_DP3 _token_ sid_DSTMOD, sid_X2 _token_ sid_REG_PS1_4, sid_R3 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R4 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_CONSTANT, sid_C0 // mul r3, r3, c(x) _token_ sid_UNARYOP, sid_MUL _token_ sid_REG_PS1_4, sid_R3 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R3 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_CONSTANT, sid_C0 // dp3 r2, r4, r4 _token_ sid_BINARYOP, sid_DP3 _token_ sid_REG_PS1_4, sid_R2 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R4 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R4 // mad r4.rgb, 1-c(x), r2, r3 _token_ sid_TERNARYOP, sid_MAD _token_ sid_REG_PS1_4, sid_R4 _token_ sid_DSTMASK, sid_RGB _token_ sid_SEPERATOR, sid_COMMA _token_ sid_PRESRCMOD, sid_INVERT _token_ sid_CONSTANT, sid_C0 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R2 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R3 // + mov r4.a, r2.r _token_ sid_UNARYOP, sid_MOV _token_ sid_REG_PS1_4, sid_R4 _token_ sid_DSTMASK, sid_A _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R2 _token_ sid_SRCREP, sid_RRRR // texld r3, r4.xyz_dz _token_ sid_TEXOP_PS1_4, sid_TEXLD _token_ sid_REG_PS1_4, sid_R3 _token_ sid_SEPERATOR, sid_COMMA _token_ sid_REG_PS1_4, sid_R4 _token_ sid_TEXSWIZZLE, sid_STRDR _token_end_ }; PS_1_4::RegModOffset PS_1_4::texm3x3spec_RegMods[] = { {8, R_BASE, 1}, {15, R_BASE, 2}, {21, C_BASE, 2}, {33, C_BASE, 2}, }; PS_1_4::MacroRegModify PS_1_4::texm3x3spec_MacroMods = { texm3x3spec, ARRAYSIZE(texm3x3spec), texm3x3spec_RegMods, ARRAYSIZE(texm3x3spec_RegMods) }; /* ********************* END OF CLASS STATIC DATA ********************************* */ PS_1_4::PS_1_4() { // allocate enough room for a large pixel shader mPhase1TEX_mi.reserve(50); mPhase2TEX_mi.reserve(30); mPhase1ALU_mi.reserve(100); mPhase2ALU_mi.reserve(100); mSymbolTypeLib = PS_1_4_SymbolTypeLib; mSymbolTypeLibCnt = ARRAYSIZE(PS_1_4_SymbolTypeLib); mRootRulePath = PS_1_x_RulePath; mRulePathLibCnt = ARRAYSIZE(PS_1_x_RulePath); // tell compiler what the symbol id is for a numeric value mValueID = sid_VALUE; // The type library must have text definitions initialized // before compiler is invoked // only need to initialize the rule database once if(LibInitialized == false) { InitSymbolTypeLib(); LibInitialized = true; } // set initial context to recognize PS base instructions mActiveContexts = ckp_PS_BASE; } bool PS_1_4::bindMachineInstInPassToFragmentShader(const MachineInstContainer & PassMachineInstructions) { size_t instIDX = 0; size_t instCount = PassMachineInstructions.size(); bool error = false; while ((instIDX < instCount) && !error) { switch(PassMachineInstructions[instIDX]) { case mi_COLOROP1: if((instIDX+7) < instCount) glColorFragmentOp1ATI(PassMachineInstructions[instIDX+1], // op PassMachineInstructions[instIDX+2], // dst PassMachineInstructions[instIDX+3], // dstMask PassMachineInstructions[instIDX+4], // dstMod PassMachineInstructions[instIDX+5], // arg1 PassMachineInstructions[instIDX+6], // arg1Rep PassMachineInstructions[instIDX+7]);// arg1Mod instIDX += 8; break; case mi_COLOROP2: if((instIDX+10) < instCount) glColorFragmentOp2ATI(PassMachineInstructions[instIDX+1], // op PassMachineInstructions[instIDX+2], // dst PassMachineInstructions[instIDX+3], // dstMask PassMachineInstructions[instIDX+4], // dstMod PassMachineInstructions[instIDX+5], // arg1 PassMachineInstructions[instIDX+6], // arg1Rep PassMachineInstructions[instIDX+7], // arg1Mod PassMachineInstructions[instIDX+8], // arg2 PassMachineInstructions[instIDX+9], // arg2Rep PassMachineInstructions[instIDX+10]);// arg2Mod instIDX += 11; break; case mi_COLOROP3: if((instIDX+13) < instCount) glColorFragmentOp3ATI(PassMachineInstructions[instIDX+1], // op PassMachineInstructions[instIDX+2], // dst PassMachineInstructions[instIDX+3], // dstMask PassMachineInstructions[instIDX+4], // dstMod PassMachineInstructions[instIDX+5], // arg1 PassMachineInstructions[instIDX+6], // arg1Rep PassMachineInstructions[instIDX+7], // arg1Mod PassMachineInstructions[instIDX+8], // arg2 PassMachineInstructions[instIDX+9], // arg2Rep PassMachineInstructions[instIDX+10], // arg2Mod PassMachineInstructions[instIDX+11], // arg2 PassMachineInstructions[instIDX+12], // arg2Rep PassMachineInstructions[instIDX+13]);// arg2Mod instIDX += 14; break; case mi_ALPHAOP1: if((instIDX+6) < instCount) glAlphaFragmentOp1ATI(PassMachineInstructions[instIDX+1], // op PassMachineInstructions[instIDX+2], // dst PassMachineInstructions[instIDX+3], // dstMod PassMachineInstructions[instIDX+4], // arg1 PassMachineInstructions[instIDX+5], // arg1Rep PassMachineInstructions[instIDX+6]); // arg1Mod instIDX += 7; break; case mi_ALPHAOP2: if((instIDX+9) < instCount) glAlphaFragmentOp2ATI(PassMachineInstructions[instIDX+1], // op PassMachineInstructions[instIDX+2], // dst PassMachineInstructions[instIDX+3], // dstMod PassMachineInstructions[instIDX+4], // arg1 PassMachineInstructions[instIDX+5], // arg1Rep PassMachineInstructions[instIDX+6], // arg1Mod PassMachineInstructions[instIDX+7], // arg2 PassMachineInstructions[instIDX+8], // arg2Rep PassMachineInstructions[instIDX+9]); // arg2Mod instIDX += 10; break; case mi_ALPHAOP3: if((instIDX+12) < instCount) glAlphaFragmentOp3ATI(PassMachineInstructions[instIDX+1], // op PassMachineInstructions[instIDX+2], // dst PassMachineInstructions[instIDX+3], // dstMod PassMachineInstructions[instIDX+4], // arg1 PassMachineInstructions[instIDX+5], // arg1Rep PassMachineInstructions[instIDX+6], // arg1Mod PassMachineInstructions[instIDX+7], // arg2 PassMachineInstructions[instIDX+8], // arg2Rep PassMachineInstructions[instIDX+9], // arg2Mod PassMachineInstructions[instIDX+10], // arg2 PassMachineInstructions[instIDX+11], // arg2Rep PassMachineInstructions[instIDX+12]); // arg2Mod instIDX += 13; break; case mi_SETCONSTANTS: if((instIDX+2) < instCount) glSetFragmentShaderConstantATI(PassMachineInstructions[instIDX+1], // dst &mConstants[PassMachineInstructions[instIDX+2]]); instIDX += 3; break; case mi_PASSTEXCOORD: if((instIDX+3) < instCount) glPassTexCoordATI(PassMachineInstructions[instIDX+1], // dst PassMachineInstructions[instIDX+2], // coord PassMachineInstructions[instIDX+3]); // swizzle instIDX += 4; break; case mi_SAMPLEMAP: if((instIDX+3) < instCount) glSampleMapATI(PassMachineInstructions[instIDX+1], // dst PassMachineInstructions[instIDX+2], // interp PassMachineInstructions[instIDX+3]); // swizzle instIDX += 4; break; default: instIDX = instCount; // should generate an error since an unknown instruction was found // instead for now the bind process is terminated and the fragment program may still function // but its output may not be what was programmed } // end of switch error = (glGetError() != GL_NO_ERROR); }// end of while return !error; } size_t PS_1_4::getMachineInst( size_t Idx) { if (Idx < mPhase1TEX_mi.size()) { return mPhase1TEX_mi[Idx]; } else { Idx -= mPhase1TEX_mi.size(); if (Idx < mPhase1ALU_mi.size()) { return mPhase1ALU_mi[Idx]; } else { Idx -= mPhase1ALU_mi.size(); if (Idx < mPhase2TEX_mi.size()) { return mPhase2TEX_mi[Idx]; } else { Idx -= mPhase2TEX_mi.size(); if (Idx < mPhase2ALU_mi.size()) { return mPhase2ALU_mi[Idx]; } } } } return 0; } void PS_1_4::addMachineInst(const PhaseType phase, const uint inst) { switch(phase) { case ptPHASE1TEX: mPhase1TEX_mi.push_back(inst); break; case ptPHASE1ALU: mPhase1ALU_mi.push_back(inst); break; case ptPHASE2TEX: mPhase2TEX_mi.push_back(inst); break; case ptPHASE2ALU: mPhase2ALU_mi.push_back(inst); break; } // end switch(phase) } size_t PS_1_4::getMachineInstCount() { return (mPhase1TEX_mi.size() + mPhase1ALU_mi.size() + mPhase2TEX_mi.size() + mPhase2ALU_mi.size()); } bool PS_1_4::bindAllMachineInstToFragmentShader() { bool passed; // there are 4 machine instruction ques to pass to the ATI fragment shader passed = bindMachineInstInPassToFragmentShader(mPhase1TEX_mi); passed &= bindMachineInstInPassToFragmentShader(mPhase1ALU_mi); passed &= bindMachineInstInPassToFragmentShader(mPhase2TEX_mi); passed &= bindMachineInstInPassToFragmentShader(mPhase2ALU_mi); return passed; } bool PS_1_4::expandMacro(const MacroRegModify & MacroMod) { RegModOffset * regmod; // set source and destination registers in macro expansion for (uint i = 0; i < MacroMod.RegModSize; i++) { regmod = &MacroMod.RegMods[i]; MacroMod.Macro[regmod->MacroOffset].mID = regmod->RegisterBase + mOpParrams[regmod->OpParramsIndex].Arg; } // turn macro support on so that ps.1.4 ALU instructions get put in phase 1 alu instruction sequence container mMacroOn = true; // pass macro tokens on to be turned into machine instructions // expand macro to ps.1.4 by doing recursive call to doPass2 bool passed = Pass2scan(MacroMod.Macro, MacroMod.MacroSize); mMacroOn = false; return passed; } bool PS_1_4::BuildMachineInst() { // check the states to see if a machine instruction can be assembled // assume all arguments have been set up bool passed = false; passed = true; // assume everything will go okay untill proven otherwise // start with machine NOP instuction // this is used after the switch to see if an instruction was set up // determine which MachineInstID is required based on the op instruction mOpType = mi_NOP; switch(mOpInst) { // ALU operations case sid_ADD: case sid_SUB: case sid_MUL: case sid_MAD: case sid_LRP: case sid_MOV: case sid_CMP: case sid_CND: case sid_DP2ADD: case sid_DP3: case sid_DP4: mOpType = (MachineInstID)(mi_COLOROP1 + mArgCnt - 1); // if context is ps.1.x and Macro not on or a phase marker was found then put all ALU ops in phase 2 ALU container if (((mActiveContexts & ckp_PS_1_1) && !mMacroOn) || mPhaseMarkerFound) mInstructionPhase = ptPHASE2ALU; else mInstructionPhase = ptPHASE1ALU; // check for alpha op in destination register which is OpParrams[0] // if no Mask for destination then make it .rgba if(mOpParrams[0].MaskRep == 0) mOpParrams[0].MaskRep = GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI | ALPHA_BIT; if (mOpParrams[0].MaskRep & ALPHA_BIT) { mDo_Alpha = true; mOpParrams[0].MaskRep -= ALPHA_BIT; if(mOpParrams[0].MaskRep == 0) mOpType = mi_NOP; // only do alpha op } break; case sid_TEXCRD: mOpType = mi_PASSTEXCOORD; if (mPhaseMarkerFound) mInstructionPhase = ptPHASE2TEX; else mInstructionPhase = ptPHASE1TEX; break; case sid_TEXLD: mOpType = mi_SAMPLEMAP; if (mPhaseMarkerFound) mInstructionPhase = ptPHASE2TEX; else mInstructionPhase = ptPHASE1TEX; break; case sid_TEX: // PS_1_1 emulation mOpType = mi_TEX; mInstructionPhase = ptPHASE1TEX; break; case sid_TEXCOORD: // PS_1_1 emulation mOpType = mi_TEXCOORD; mInstructionPhase = ptPHASE1TEX; break; case sid_TEXREG2AR: passed = expandMacro(texreg2ar_MacroMods); break; case sid_TEXREG2GB: passed = expandMacro(texreg2gb_MacroMods); break; case sid_TEXDP3: passed = expandMacro(texdp3_MacroMods); break; case sid_TEXDP3TEX: passed = expandMacro(texdp3tex_MacroMods); break; case sid_TEXM3X2PAD: passed = expandMacro(texm3x2pad_MacroMods); break; case sid_TEXM3X2TEX: passed = expandMacro(texm3x2tex_MacroMods); break; case sid_TEXM3X3PAD: // only 2 texm3x3pad instructions allowed // use count to modify macro to select which mask to use if(mTexm3x3padCount<2) { texm3x3pad[4].mID = sid_R + mTexm3x3padCount; mTexm3x3padCount++; passed = expandMacro(texm3x3pad_MacroMods); } else passed = false; break; case sid_TEXM3X3TEX: passed = expandMacro(texm3x3tex_MacroMods); break; case sid_DEF: mOpType = mi_SETCONSTANTS; mInstructionPhase = ptPHASE1TEX; break; case sid_PHASE: // PS_1_4 only mPhaseMarkerFound = true; break; } // end of switch if(passed) passed = expandMachineInstruction(); return passed; } bool PS_1_4::expandMachineInstruction() { // now push instructions onto MachineInstructions container // assume that an instruction will be expanded bool passed = true; if (mOpType != mi_NOP) { // a machine instruction will be built // this is currently the last one being built so keep track of it if (mInstructionPhase == ptPHASE2ALU) { mSecondLastInstructionPos = mLastInstructionPos; mLastInstructionPos = mPhase2ALU_mi.size(); } switch (mOpType) { case mi_COLOROP1: case mi_COLOROP2: case mi_COLOROP3: { addMachineInst(mInstructionPhase, mOpType); addMachineInst(mInstructionPhase, mSymbolTypeLib[mOpInst].mPass2Data); // send all parameters to machine inst container for(int i=0; i<=mArgCnt; i++) { addMachineInst(mInstructionPhase, mOpParrams[i].Arg); addMachineInst(mInstructionPhase, mOpParrams[i].MaskRep); addMachineInst(mInstructionPhase, mOpParrams[i].Mod); // check if source register read is valid in this phase passed &= isRegisterReadValid(mInstructionPhase, i); } // record which registers were written to and in which phase // mOpParrams[0].Arg is always the destination register r0 -> r5 updateRegisterWriteState(mInstructionPhase); } break; case mi_SETCONSTANTS: addMachineInst(mInstructionPhase, mOpType); addMachineInst(mInstructionPhase, mOpParrams[0].Arg); // dst addMachineInst(mInstructionPhase, mConstantsPos); // index into constants array break; case mi_PASSTEXCOORD: case mi_SAMPLEMAP: // if source is a temp register than place instruction in phase 2 Texture ops if ((mOpParrams[1].Arg >= GL_REG_0_ATI) && (mOpParrams[1].Arg <= GL_REG_5_ATI)) { mInstructionPhase = ptPHASE2TEX; } addMachineInst(mInstructionPhase, mOpType); addMachineInst(mInstructionPhase, mOpParrams[0].Arg); // dst addMachineInst(mInstructionPhase, mOpParrams[1].Arg); // coord addMachineInst(mInstructionPhase, mOpParrams[1].MaskRep + GL_SWIZZLE_STR_ATI); // swizzle // record which registers were written to and in which phase // mOpParrams[0].Arg is always the destination register r0 -> r5 updateRegisterWriteState(mInstructionPhase); break; case mi_TEX: // PS_1_1 emulation - turn CISC into RISC - phase 1 addMachineInst(mInstructionPhase, mi_SAMPLEMAP); addMachineInst(mInstructionPhase, mOpParrams[0].Arg); // dst // tex tx becomes texld rx, tx with x: 0 - 3 addMachineInst(mInstructionPhase, mOpParrams[0].Arg - GL_REG_0_ATI + GL_TEXTURE0_ARB); // interp // default to str which fills rgb of destination register addMachineInst(mInstructionPhase, GL_SWIZZLE_STR_ATI); // swizzle // record which registers were written to and in which phase // mOpParrams[0].Arg is always the destination register r0 -> r5 updateRegisterWriteState(mInstructionPhase); break; case mi_TEXCOORD: // PS_1_1 emulation - turn CISC into RISC - phase 1 addMachineInst(mInstructionPhase, mi_PASSTEXCOORD); addMachineInst(mInstructionPhase, mOpParrams[0].Arg); // dst // texcoord tx becomes texcrd rx, tx with x: 0 - 3 addMachineInst(mInstructionPhase, mOpParrams[0].Arg - GL_REG_0_ATI + GL_TEXTURE0_ARB); // interp // default to str which fills rgb of destination register addMachineInst(mInstructionPhase, GL_SWIZZLE_STR_ATI); // swizzle // record which registers were written to and in which phase // mOpParrams[0].Arg is always the destination register r0 -> r5 updateRegisterWriteState(mInstructionPhase); break; } // end of switch (mOpType) } // end of if (mOpType != mi_NOP) if(mDo_Alpha) { // process alpha channel // // a scaler machine instruction will be built // this is currently the last one being built so keep track of it if (mInstructionPhase == ptPHASE2ALU) { mSecondLastInstructionPos = mLastInstructionPos; mLastInstructionPos = mPhase2ALU_mi.size(); } MachineInstID alphaoptype = (MachineInstID)(mi_ALPHAOP1 + mArgCnt - 1); addMachineInst(mInstructionPhase, alphaoptype); addMachineInst(mInstructionPhase, mSymbolTypeLib[mOpInst].mPass2Data); // put all parameters in instruction que for(int i=0; i<=mArgCnt; i++) { addMachineInst(mInstructionPhase, mOpParrams[i].Arg); // destination parameter has no mask since it is the alpha channel // don't push mask for parrameter 0 (dst) if(i>0) addMachineInst(mInstructionPhase, mOpParrams[i].MaskRep); addMachineInst(mInstructionPhase, mOpParrams[i].Mod); // check if source register read is valid in this phase passed &= isRegisterReadValid(mInstructionPhase, i); } updateRegisterWriteState(mInstructionPhase); } // instruction passed on to machine instruction so clear the pipe clearMachineInstState(); return passed; } void PS_1_4::updateRegisterWriteState(const PhaseType phase) { int reg_offset = mOpParrams[0].Arg - GL_REG_0_ATI; switch(phase) { case ptPHASE1TEX: case ptPHASE1ALU: Phase_RegisterUsage[reg_offset].Phase1Write = true; break; case ptPHASE2TEX: case ptPHASE2ALU: Phase_RegisterUsage[reg_offset].Phase2Write = true; break; } // end switch(phase) } bool PS_1_4::isRegisterReadValid(const PhaseType phase, const int param) { bool passed = true; // assume everything will go alright // if in phase 2 ALU and argument is a source if((phase == ptPHASE2ALU) && (param>0)) { // is source argument a temp register r0 - r5? if((mOpParrams[param].Arg >= GL_REG_0_ATI) && (mOpParrams[param].Arg <= GL_REG_5_ATI)) { int reg_offset = mOpParrams[param].Arg - GL_REG_0_ATI; // if register was not written to in phase 2 but was in phase 1 if((Phase_RegisterUsage[reg_offset].Phase2Write == false) && Phase_RegisterUsage[reg_offset].Phase1Write) { // only perform register pass if there are ALU instructions in phase 1 if(mPhase1ALU_mi.size() > 0) { // build machine instructions for passing a register from phase 1 to phase 2 // NB: only rgb components of register will get passed addMachineInst(ptPHASE2TEX, mi_PASSTEXCOORD); addMachineInst(ptPHASE2TEX, mOpParrams[param].Arg); // dst addMachineInst(ptPHASE2TEX, mOpParrams[param].Arg); // coord addMachineInst(ptPHASE2TEX, GL_SWIZZLE_STR_ATI); // swizzle // mark register as being written to Phase_RegisterUsage[reg_offset].Phase2Write = true; } } // register can not be used because it has not been written to previously else passed = false; } } return passed; } void PS_1_4::optimize() { // perform some optimizations on ps.1.1 machine instructions if (mActiveContexts & ckp_PS_1_1) { // need to check last few instructions to make sure r0 is set // ps.1.1 emulation uses r4 for r0 so last couple of instructions will probably require // changine destination register back to r0 if (mLastInstructionPos < mPhase2ALU_mi.size()) { // first argument at mLastInstructionPos + 2 is destination register for all ps.1.1 ALU instructions mPhase2ALU_mi[mLastInstructionPos + 2] = GL_REG_0_ATI; // if was an alpha op only then modify second last instruction destination register if ((mPhase2ALU_mi[mLastInstructionPos] == mi_ALPHAOP1) || (mPhase2ALU_mi[mLastInstructionPos] == mi_ALPHAOP2) || (mPhase2ALU_mi[mLastInstructionPos] == mi_ALPHAOP3) ) { mPhase2ALU_mi[mSecondLastInstructionPos + 2] = GL_REG_0_ATI; } }// end if (mLastInstructionPos < mMachineInstructions.size()) }// end if (mActiveContexts & ckp_PS_1_1) } void PS_1_4::clearMachineInstState() { // set current Machine Instruction State to baseline mOpType = mi_NOP; mOpInst = sid_INVALID; mDo_Alpha = false; mArgCnt = 0; for(int i=0; imID; } else passed = false; break; case sid_DSTMASK: case sid_SRCREP: case sid_TEXSWIZZLE: // could be a dst mask or a arg replicator // if dst mask and alpha included then make up a alpha instruction: maybe best to wait until instruction args completed mOpParrams[mArgCnt].MaskRep = cursymboldef->mPass2Data; break; case sid_DSTMOD: case sid_DSTSAT: case sid_PRESRCMOD: case sid_POSTSRCMOD: mOpParrams[mArgCnt].Mod |= cursymboldef->mPass2Data; break; case sid_NUMVAL: passed = setOpParram(cursymboldef); // keep track of how many values are used // update Constants array position mConstantsPos++; break; case sid_SEPERATOR: mArgCnt++; break; } // end of switch if(!passed) break; }// end of for: imPass2Data; } else success = false; return success; } // ********************************************************************************* // this is where the tests are carried out to make sure the PS_1_4 compiler works #ifdef _DEBUG // check the functionality of functions in PS_1_4: each test will print to the output file PASSED of FAILED void PS_1_4::test() { struct test1result{ char character; int line; }; struct testfloatresult{ char *teststr; float fvalue; int charsize; }; char TestStr1[] = " \n\r //c \n\r// test\n\r \t c - \n\r , e"; test1result test1results[] = { {'c', 4}, {'-', 4}, {',', 5}, {'e', 5} }; testfloatresult testfloatresults[] = { {"1 test", 1.0f, 1}, {"2.3f test", 2.3f, 3}, {"-0.5 test", -0.5f, 4}, {" 23.6 test", 23.6f, 5}, {" -0.021 test", -0.021f, 8}, {"12 test", 12.0f, 2}, {"3test", 3.0f, 1} }; SymbolID test3result[] = { sid_MOV, sid_COMMA, sid_MUL, sid_ADD, sid_NEGATE, sid_T0 }; #define PART2INST 17 char TestStr3[] = "mov r0,c1"; char TestSymbols[] = "mov"; char passed[] = "PASSED\n"; char failed[] = "***** FAILED *****\n"; int resultID = 0; // loop variable used in for loops int i; fp = fopen("ASMTests.txt", "wt"); // ************************************************************** // first test: see if positionToNextSymbol can find a valid Symbol fprintf(fp, "Testing: positionToNextSymbol\n"); mSource = TestStr1; mCharPos = 0; mCurrentLine = 1; mEndOfSource = (int)strlen(mSource); while (positionToNextSymbol()) { fprintf(fp," character found: [%c] Line:%d : " , mSource[mCharPos], mCurrentLine); if( (mSource[mCharPos] == test1results[resultID].character) && (mCurrentLine==test1results[resultID].line)) fprintf(fp, passed); else fprintf(fp, failed); resultID++; mCharPos++; } fprintf(fp, "finished testing: positionToNextSymbol\n"); // ************************************************************** // Second Test // did the type lib get initialized properly with a default name index fprintf(fp, "\nTesting: getTypeDefText\n"); char* resultstr = getTypeDefText(sid_MOV); fprintf(fp, " default name of mov is: [%s]: %s", resultstr, (strcmp("mov", resultstr)==0)?passed:failed); fprintf(fp, "finished testing: getTypeDefText\n"); // ************************************************************** // ************************************************************** // fourth test - does isSymbol work correctly fprintf(fp, "\nTesting: isSymbol\n"); mSource = TestStr3; mCharPos = 0; fprintf(fp, " before: [%s]\n", mSource + mCharPos); fprintf(fp, " symbol to find: [%s]\n", TestSymbols); if(isSymbol(TestSymbols, resultID)) { fprintf(fp, " after: [%s] : %s", mSource + resultID + 1, (mSource[resultID + 1] == 'r')? passed:failed); } else fprintf(fp, failed); fprintf(fp," symbol size: %d\n", resultID); fprintf(fp, "finished testing: isSymbol\n"); // ************************************************************** fprintf(fp, "\nTesting: isFloatValue\n"); float fvalue = 0; int charsize = 0; char teststrfloat1[] = "1 test"; mCharPos = 0; int testsize = ARRAYSIZE(testfloatresults); for(i=0; i