home *** CD-ROM | disk | FTP | other *** search
- /* $Id: vpparse.c,v 1.15 2002/11/27 03:40:13 brianp Exp $ */
-
- /*
- * Mesa 3-D graphics library
- * Version: 5.1
- *
- * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
- /*
- * -------- Regarding NV_vertex_program --------
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * o Redistribution of the source code must contain a copyright notice
- * and this list of conditions;
- *
- * o Redistribution in binary and source code form must contain the
- * following Notice in the software and any documentation and/or other
- * materials provided with the distribution; and
- *
- * o The name of Nvidia may not be used to promote or endorse software
- * derived from the software.
- *
- * NOTICE: Nvidia hereby grants to each recipient a non-exclusive worldwide
- * royalty free patent license under patent claims that are licensable by
- * Nvidia and which are necessarily required and for which no commercially
- * viable non infringing alternative exists to make, use, sell, offer to sell,
- * import and otherwise transfer the vertex extension for the Mesa 3D Graphics
- * Library as distributed in source code and object code form. No hardware or
- * hardware implementation (including a semiconductor implementation and chips)
- * are licensed hereunder. If a recipient makes a patent claim or institutes
- * patent litigation against Nvidia or Nvidia's customers for use or sale of
- * Nvidia products, then this license grant as to such recipient shall
- * immediately terminate and recipient immediately agrees to cease use and
- * distribution of the Mesa Program and derivatives thereof.
- *
- * THE MESA 3D GRAPHICS LIBRARY IS PROVIDED ON AN "AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
- * WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-NFRINGEMENT
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * NVIDIA SHALL NOT HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
- * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE MESA 3D GRAPHICS
- * LIBRARY OR EVIDENCE OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDR, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * If you do not comply with this agreement, then Nvidia may cancel the license
- * and rights granted herein.
- * ---------------------------------------------
- */
-
- /**
- * \file vpparse.c
- * \brief Vertex program parser.
- * \author Brian Paul
- */
-
-
- #include "glheader.h"
- #include "context.h"
- #include "hash.h"
- #include "imports.h"
- #include "macros.h"
- #include "mtypes.h"
- #include "vpparse.h"
-
-
-
- /************************ Symbol Table ******************************/
-
- /* A simple symbol table implementation for ARB_vertex_program
- * (not used yet)
- */
-
- #if 000
- struct symbol
- {
- GLubyte *name;
- GLint value;
- struct symbol *next;
- };
-
- static struct symbol *SymbolTable = NULL;
-
- static GLboolean
- IsSymbol(const GLubyte *symbol)
- {
- struct symbol *s;
- for (s = SymbolTable; s; s = s->next) {
- if (strcmp((char *) symbol, (char *)s->name) == 0)
- return GL_TRUE;
- }
- return GL_FALSE;
- }
-
- static GLint
- GetSymbolValue(const GLubyte *symbol)
- {
- struct symbol *s;
- for (s = SymbolTable; s; s = s->next) {
- if (strcmp((char *) symbol, (char *)s->name) == 0)
- return s->value;
- }
- return 0;
- }
-
- static void
- AddSymbol(const GLubyte *symbol, GLint value)
- {
- struct symbol *s = MALLOC_STRUCT(symbol);
- if (s) {
- s->name = (GLubyte *) strdup((char *) symbol);
- s->value = value;
- s->next = SymbolTable;
- SymbolTable = s;
- }
- }
-
- static void
- ResetSymbolTable(void)
- {
- struct symbol *s, *next;
- for (s = SymbolTable; s; s = next) {
- next = s->next;
- FREE(s->name);
- FREE(s);
- s = next;
- }
- SymbolTable = NULL;
- }
- #endif
-
- /***************************** Parsing ******************************/
-
-
- static GLboolean IsLetter(GLubyte b)
- {
- return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z');
- }
-
-
- static GLboolean IsDigit(GLubyte b)
- {
- return b >= '0' && b <= '9';
- }
-
-
- static GLboolean IsWhitespace(GLubyte b)
- {
- return b == ' ' || b == '\t' || b == '\n' || b == '\r';
- }
-
-
- /**
- * Starting at 'str' find the next token. A token can be an integer,
- * an identifier or punctuation symbol.
- * \return <= 0 we found an error, else, return number of characters parsed.
- */
- static GLint
- GetToken(const GLubyte *str, GLubyte *token)
- {
- GLint i = 0, j = 0;
-
- token[0] = 0;
-
- /* skip whitespace and comments */
- while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) {
- if (str[i] == '#') {
- /* skip comment */
- while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
- i++;
- }
- }
- else {
- /* skip whitespace */
- i++;
- }
- }
-
- if (str[i] == 0)
- return -i;
-
- /* try matching an integer */
- while (str[i] && IsDigit(str[i])) {
- token[j++] = str[i++];
- }
- if (j > 0 || !str[i]) {
- token[j] = 0;
- return i;
- }
-
- /* try matching an identifier */
- if (IsLetter(str[i])) {
- while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) {
- token[j++] = str[i++];
- }
- token[j] = 0;
- return i;
- }
-
- /* punctuation */
- if (str[i]) {
- token[0] = str[i++];
- token[1] = 0;
- return i;
- }
-
- /* end of input */
- token[0] = 0;
- return i;
- }
-
-
- /**
- * Get next token from input stream and increment stream pointer past token.
- */
- static GLboolean
- Parse_Token(const GLubyte **s, GLubyte *token)
- {
- GLint i;
- i = GetToken(*s, token);
- if (i <= 0) {
- *s += (-i);
- return GL_FALSE;
- }
- *s += i;
- return GL_TRUE;
- }
-
-
- /**
- * Get next token from input stream but don't increment stream pointer.
- */
- static GLboolean
- Peek_Token(const GLubyte **s, GLubyte *token)
- {
- GLint i, len;
- i = GetToken(*s, token);
- if (i <= 0) {
- *s += (-i);
- return GL_FALSE;
- }
- len = _mesa_strlen((char *) token);
- *s += (i - len);
- return GL_TRUE;
- }
-
-
- /**
- * String equality test
- */
- static GLboolean
- StrEq(const GLubyte *a, const GLubyte *b)
- {
- GLint i;
- for (i = 0; a[i] && b[i] && a[i] == b[i]; i++)
- ;
- if (a[i] == 0 && b[i] == 0)
- return GL_TRUE;
- else
- return GL_FALSE;
- }
-
-
- /**********************************************************************/
-
- static const char *InputRegisters[] = {
- "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7",
- "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
- };
-
- static const char *OutputRegisters[] = {
- "HPOS", "COL0", "COL1", "BFC0", "BFC1", "FOGC", "PSIZ",
- "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
- };
-
- static const char *Opcodes[] = {
- "MOV", "LIT", "RCP", "RSQ", "EXP", "LOG", "MUL", "ADD", "DP3", "DP4",
- "DST", "MIN", "MAX", "SLT", "SGE", "MAD", "ARL", "DPH", "RCC", "SUB",
- "ABS", "END", NULL
- };
-
-
- #ifdef DEBUG
-
- #define PARSE_ERROR \
- do { \
- _mesa_printf("vpparse.c error at %d: parse error\n", __LINE__); \
- return GL_FALSE; \
- } while(0)
-
- #define PARSE_ERROR1(msg) \
- do { \
- _mesa_printf("vpparse.c error at %d: %s\n", __LINE__, msg); \
- return GL_FALSE; \
- } while(0)
-
- #define PARSE_ERROR2(msg1, msg2) \
- do { \
- _mesa_printf("vpparse.c error at %d: %s %s\n", __LINE__, msg1, msg2); \
- return GL_FALSE; \
- } while(0)
-
- #else
-
- #define PARSE_ERROR return GL_FALSE
- #define PARSE_ERROR1(msg1) return GL_FALSE
- #define PARSE_ERROR2(msg1, msg2) return GL_FALSE
-
- #endif
-
-
- static GLuint
- IsProgRegister(GLuint r)
- {
- return (GLuint) (r >= VP_PROG_REG_START && r <= VP_PROG_REG_END);
- }
-
- static GLuint
- IsInputRegister(GLuint r)
- {
- return (GLuint) (r >= VP_INPUT_REG_START && r <= VP_INPUT_REG_END);
- }
-
- static GLuint
- IsOutputRegister(GLuint r)
- {
- return (GLuint) (r >= VP_OUTPUT_REG_START && r <= VP_OUTPUT_REG_END);
- }
-
-
-
- /**********************************************************************/
-
- /* XXX
- * These shouldn't be globals as that makes the parser non-reentrant.
- * We should really define a "ParserContext" class which contains these
- * and the <s> pointer into the program text.
- */
- static GLboolean IsStateProgram = GL_FALSE;
- static GLboolean IsPositionInvariant = GL_FALSE;
- static GLboolean IsVersion1_1 = GL_FALSE;
-
- /**
- * Try to match 'pattern' as the next token after any whitespace/comments.
- */
- static GLboolean
- Parse_String(const GLubyte **s, const char *pattern)
- {
- GLint i;
-
- /* skip whitespace and comments */
- while (IsWhitespace(**s) || **s == '#') {
- if (**s == '#') {
- while (**s && (**s != '\n' && **s != '\r')) {
- *s += 1;
- }
- }
- else {
- /* skip whitespace */
- *s += 1;
- }
- }
-
- /* Try to match the pattern */
- for (i = 0; pattern[i]; i++) {
- if (**s != pattern[i])
- PARSE_ERROR2("failed to match", pattern); /* failure */
- *s += 1;
- }
-
- return GL_TRUE; /* success */
- }
-
-
- /**
- * Parse a temporary register: Rnn
- */
- static GLboolean
- Parse_TempReg(const GLubyte **s, GLint *tempRegNum)
- {
- GLubyte token[100];
-
- /* Should be 'R##' */
- if (!Parse_Token(s, token))
- PARSE_ERROR;
- if (token[0] != 'R')
- PARSE_ERROR1("Expected R##");
-
- if (IsDigit(token[1])) {
- GLint reg = _mesa_atoi((char *) (token + 1));
- if (reg >= VP_NUM_TEMP_REGS)
- PARSE_ERROR1("Bad temporary register name");
- *tempRegNum = VP_TEMP_REG_START + reg;
- }
- else {
- PARSE_ERROR1("Bad temporary register name");
- }
-
- return GL_TRUE;
- }
-
-
- /**
- * Parse address register "A0.x"
- */
- static GLboolean
- Parse_AddrReg(const GLubyte **s)
- {
- /* match 'A0' */
- if (!Parse_String(s, "A0"))
- PARSE_ERROR;
-
- /* match '.' */
- if (!Parse_String(s, "."))
- PARSE_ERROR;
-
- /* match 'x' */
- if (!Parse_String(s, "x"))
- PARSE_ERROR;
-
- return GL_TRUE;
- }
-
-
- /**
- * Parse absolute program parameter register "c[##]"
- */
- static GLboolean
- Parse_AbsParamReg(const GLubyte **s, GLint *regNum)
- {
- GLubyte token[100];
-
- if (!Parse_String(s, "c"))
- PARSE_ERROR;
-
- if (!Parse_String(s, "["))
- PARSE_ERROR;
-
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (IsDigit(token[0])) {
- /* a numbered program parameter register */
- GLint reg = _mesa_atoi((char *) token);
- if (reg >= VP_NUM_PROG_REGS)
- PARSE_ERROR1("Bad constant program number");
- *regNum = VP_PROG_REG_START + reg;
- }
- else {
- PARSE_ERROR;
- }
-
- if (!Parse_String(s, "]"))
- PARSE_ERROR;
-
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_ParamReg(const GLubyte **s, struct vp_src_register *srcReg)
- {
- GLubyte token[100];
-
- if (!Parse_String(s, "c"))
- PARSE_ERROR;
-
- if (!Parse_String(s, "["))
- PARSE_ERROR;
-
- if (!Peek_Token(s, token))
- PARSE_ERROR;
-
- if (IsDigit(token[0])) {
- /* a numbered program parameter register */
- GLint reg;
- (void) Parse_Token(s, token);
- reg = _mesa_atoi((char *) token);
- if (reg >= VP_NUM_PROG_REGS)
- PARSE_ERROR1("Bad constant program number");
- srcReg->Register = VP_PROG_REG_START + reg;
- }
- else if (StrEq(token, (GLubyte *) "A0")) {
- /* address register "A0.x" */
- if (!Parse_AddrReg(s))
- PARSE_ERROR;
-
- srcReg->RelAddr = GL_TRUE;
- srcReg->Register = 0;
-
- /* Look for +/-N offset */
- if (!Peek_Token(s, token))
- PARSE_ERROR;
-
- if (token[0] == '-' || token[0] == '+') {
- const GLubyte sign = token[0];
- (void) Parse_Token(s, token); /* consume +/- */
-
- /* an integer should be next */
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (IsDigit(token[0])) {
- const GLint k = _mesa_atoi((char *) token);
- if (sign == '-') {
- if (k > 64)
- PARSE_ERROR1("Bad address offset");
- srcReg->Register = -k;
- }
- else {
- if (k > 63)
- PARSE_ERROR1("Bad address offset");
- srcReg->Register = k;
- }
- }
- else {
- PARSE_ERROR;
- }
- }
- else {
- /* probably got a ']', catch it below */
- }
- }
- else {
- PARSE_ERROR;
- }
-
- /* Match closing ']' */
- if (!Parse_String(s, "]"))
- PARSE_ERROR;
-
- return GL_TRUE;
- }
-
-
- /**
- * Parse v[#] or v[<name>]
- */
- static GLboolean
- Parse_AttribReg(const GLubyte **s, GLint *tempRegNum)
- {
- GLubyte token[100];
- GLint j;
-
- /* Match 'v' */
- if (!Parse_String(s, "v"))
- PARSE_ERROR;
-
- /* Match '[' */
- if (!Parse_String(s, "["))
- PARSE_ERROR;
-
- /* match number or named register */
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (IsStateProgram && token[0] != '0')
- PARSE_ERROR1("Only v[0] accessible in vertex state programs");
-
- if (IsDigit(token[0])) {
- GLint reg = _mesa_atoi((char *) token);
- if (reg >= VP_NUM_INPUT_REGS)
- PARSE_ERROR1("Bad vertex attribute register name");
- *tempRegNum = VP_INPUT_REG_START + reg;
- }
- else {
- for (j = 0; InputRegisters[j]; j++) {
- if (StrEq(token, (const GLubyte *) InputRegisters[j])) {
- *tempRegNum = VP_INPUT_REG_START + j;
- break;
- }
- }
- if (!InputRegisters[j]) {
- /* unknown input register label */
- PARSE_ERROR2("Bad register name", token);
- }
- }
-
- /* Match '[' */
- if (!Parse_String(s, "]"))
- PARSE_ERROR;
-
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_OutputReg(const GLubyte **s, GLint *outputRegNum)
- {
- GLubyte token[100];
- GLint start, j;
-
- /* Match 'o' */
- if (!Parse_String(s, "o"))
- PARSE_ERROR;
-
- /* Match '[' */
- if (!Parse_String(s, "["))
- PARSE_ERROR;
-
- /* Get output reg name */
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (IsPositionInvariant)
- start = 1; /* skip HPOS register name */
- else
- start = 0;
-
- /* try to match an output register name */
- for (j = start; OutputRegisters[j]; j++) {
- if (StrEq(token, (const GLubyte *) OutputRegisters[j])) {
- *outputRegNum = VP_OUTPUT_REG_START + j;
- break;
- }
- }
- if (!OutputRegisters[j])
- PARSE_ERROR1("Unrecognized output register name");
-
- /* Match ']' */
- if (!Parse_String(s, "]"))
- PARSE_ERROR1("Expected ]");
-
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_MaskedDstReg(const GLubyte **s, struct vp_dst_register *dstReg)
- {
- GLubyte token[100];
-
- /* Dst reg can be R<n> or o[n] */
- if (!Peek_Token(s, token))
- PARSE_ERROR;
-
- if (token[0] == 'R') {
- /* a temporary register */
- if (!Parse_TempReg(s, &dstReg->Register))
- PARSE_ERROR;
- }
- else if (!IsStateProgram && token[0] == 'o') {
- /* an output register */
- if (!Parse_OutputReg(s, &dstReg->Register))
- PARSE_ERROR;
- }
- else if (IsStateProgram && token[0] == 'c') {
- /* absolute program parameter register */
- if (!Parse_AbsParamReg(s, &dstReg->Register))
- PARSE_ERROR;
- }
- else {
- PARSE_ERROR1("Bad destination register name");
- }
-
- /* Parse optional write mask */
- if (!Peek_Token(s, token))
- PARSE_ERROR;
-
- if (token[0] == '.') {
- /* got a mask */
- GLint k = 0;
-
- if (!Parse_String(s, "."))
- PARSE_ERROR;
-
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- dstReg->WriteMask[0] = GL_FALSE;
- dstReg->WriteMask[1] = GL_FALSE;
- dstReg->WriteMask[2] = GL_FALSE;
- dstReg->WriteMask[3] = GL_FALSE;
-
- if (token[k] == 'x') {
- dstReg->WriteMask[0] = GL_TRUE;
- k++;
- }
- if (token[k] == 'y') {
- dstReg->WriteMask[1] = GL_TRUE;
- k++;
- }
- if (token[k] == 'z') {
- dstReg->WriteMask[2] = GL_TRUE;
- k++;
- }
- if (token[k] == 'w') {
- dstReg->WriteMask[3] = GL_TRUE;
- k++;
- }
- if (k == 0) {
- PARSE_ERROR1("Bad writemask character");
- }
- return GL_TRUE;
- }
- else {
- dstReg->WriteMask[0] = GL_TRUE;
- dstReg->WriteMask[1] = GL_TRUE;
- dstReg->WriteMask[2] = GL_TRUE;
- dstReg->WriteMask[3] = GL_TRUE;
- return GL_TRUE;
- }
- }
-
-
- static GLboolean
- Parse_SwizzleSrcReg(const GLubyte **s, struct vp_src_register *srcReg)
- {
- GLubyte token[100];
-
- srcReg->RelAddr = GL_FALSE;
-
- /* check for '-' */
- if (!Peek_Token(s, token))
- PARSE_ERROR;
- if (token[0] == '-') {
- (void) Parse_String(s, "-");
- srcReg->Negate = GL_TRUE;
- if (!Peek_Token(s, token))
- PARSE_ERROR;
- }
- else {
- srcReg->Negate = GL_FALSE;
- }
-
- /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
- if (token[0] == 'R') {
- if (!Parse_TempReg(s, &srcReg->Register))
- PARSE_ERROR;
- }
- else if (token[0] == 'c') {
- if (!Parse_ParamReg(s, srcReg))
- PARSE_ERROR;
- }
- else if (token[0] == 'v') {
- if (!Parse_AttribReg(s, &srcReg->Register))
- PARSE_ERROR;
- }
- else {
- PARSE_ERROR2("Bad source register name", token);
- }
-
- /* init swizzle fields */
- srcReg->Swizzle[0] = 0;
- srcReg->Swizzle[1] = 1;
- srcReg->Swizzle[2] = 2;
- srcReg->Swizzle[3] = 3;
-
- /* Look for optional swizzle suffix */
- if (!Peek_Token(s, token))
- PARSE_ERROR;
- if (token[0] == '.') {
- (void) Parse_String(s, "."); /* consume . */
-
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (token[1] == 0) {
- /* single letter swizzle */
- if (token[0] == 'x')
- ASSIGN_4V(srcReg->Swizzle, 0, 0, 0, 0)
- else if (token[0] == 'y')
- ASSIGN_4V(srcReg->Swizzle, 1, 1, 1, 1)
- else if (token[0] == 'z')
- ASSIGN_4V(srcReg->Swizzle, 2, 2, 2, 2)
- else if (token[0] == 'w')
- ASSIGN_4V(srcReg->Swizzle, 3, 3, 3, 3)
- else
- PARSE_ERROR1("Expected x, y, z, or w");
- }
- else {
- /* 2, 3 or 4-component swizzle */
- GLint k;
- for (k = 0; token[k] && k < 5; k++) {
- if (token[k] == 'x')
- srcReg->Swizzle[k] = 0;
- else if (token[k] == 'y')
- srcReg->Swizzle[k] = 1;
- else if (token[k] == 'z')
- srcReg->Swizzle[k] = 2;
- else if (token[k] == 'w')
- srcReg->Swizzle[k] = 3;
- else
- PARSE_ERROR;
- }
- if (k >= 5)
- PARSE_ERROR;
- }
- }
-
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_ScalarSrcReg(const GLubyte **s, struct vp_src_register *srcReg)
- {
- GLubyte token[100];
-
- srcReg->RelAddr = GL_FALSE;
-
- /* check for '-' */
- if (!Peek_Token(s, token))
- PARSE_ERROR;
- if (token[0] == '-') {
- srcReg->Negate = GL_TRUE;
- (void) Parse_String(s, "-"); /* consume '-' */
- if (!Peek_Token(s, token))
- PARSE_ERROR;
- }
- else {
- srcReg->Negate = GL_FALSE;
- }
-
- /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
- if (token[0] == 'R') {
- if (!Parse_TempReg(s, &srcReg->Register))
- PARSE_ERROR;
- }
- else if (token[0] == 'c') {
- if (!Parse_ParamReg(s, srcReg))
- PARSE_ERROR;
- }
- else if (token[0] == 'v') {
- if (!Parse_AttribReg(s, &srcReg->Register))
- PARSE_ERROR;
- }
- else {
- PARSE_ERROR2("Bad source register name", token);
- }
-
- /* Look for .[xyzw] suffix */
- if (!Parse_String(s, "."))
- PARSE_ERROR;
-
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (token[0] == 'x' && token[1] == 0) {
- srcReg->Swizzle[0] = 0;
- }
- else if (token[0] == 'y' && token[1] == 0) {
- srcReg->Swizzle[0] = 1;
- }
- else if (token[0] == 'z' && token[1] == 0) {
- srcReg->Swizzle[0] = 2;
- }
- else if (token[0] == 'w' && token[1] == 0) {
- srcReg->Swizzle[0] = 3;
- }
- else {
- PARSE_ERROR1("Bad scalar source suffix");
- }
- srcReg->Swizzle[1] = srcReg->Swizzle[2] = srcReg->Swizzle[3] = 0;
-
- return GL_TRUE;
- }
-
-
- static GLint
- Parse_UnaryOpInstruction(const GLubyte **s, struct vp_instruction *inst)
- {
- GLubyte token[100];
-
- /* opcode */
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (StrEq(token, (GLubyte *) "MOV")) {
- inst->Opcode = MOV;
- }
- else if (StrEq(token, (GLubyte *) "LIT")) {
- inst->Opcode = LIT;
- }
- else if (StrEq(token, (GLubyte *) "ABS") && IsVersion1_1) {
- inst->Opcode = ABS;
- }
- else {
- PARSE_ERROR;
- }
-
- /* dest reg */
- if (!Parse_MaskedDstReg(s, &inst->DstReg))
- PARSE_ERROR;
-
- /* comma */
- if (!Parse_String(s, ","))
- PARSE_ERROR;
-
- /* src arg */
- if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
- PARSE_ERROR;
-
- /* semicolon */
- if (!Parse_String(s, ";"))
- PARSE_ERROR;
-
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_BiOpInstruction(const GLubyte **s, struct vp_instruction *inst)
- {
- GLubyte token[100];
-
- /* opcode */
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (StrEq(token, (GLubyte *) "MUL")) {
- inst->Opcode = MUL;
- }
- else if (StrEq(token, (GLubyte *) "ADD")) {
- inst->Opcode = ADD;
- }
- else if (StrEq(token, (GLubyte *) "DP3")) {
- inst->Opcode = DP3;
- }
- else if (StrEq(token, (GLubyte *) "DP4")) {
- inst->Opcode = DP4;
- }
- else if (StrEq(token, (GLubyte *) "DST")) {
- inst->Opcode = DST;
- }
- else if (StrEq(token, (GLubyte *) "MIN")) {
- inst->Opcode = ADD;
- }
- else if (StrEq(token, (GLubyte *) "MAX")) {
- inst->Opcode = ADD;
- }
- else if (StrEq(token, (GLubyte *) "SLT")) {
- inst->Opcode = SLT;
- }
- else if (StrEq(token, (GLubyte *) "SGE")) {
- inst->Opcode = SGE;
- }
- else if (StrEq(token, (GLubyte *) "DPH") && IsVersion1_1) {
- inst->Opcode = DPH;
- }
- else if (StrEq(token, (GLubyte *) "SUB") && IsVersion1_1) {
- inst->Opcode = SUB;
- }
- else {
- PARSE_ERROR;
- }
-
- /* dest reg */
- if (!Parse_MaskedDstReg(s, &inst->DstReg))
- PARSE_ERROR;
-
- /* comma */
- if (!Parse_String(s, ","))
- PARSE_ERROR;
-
- /* first src arg */
- if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
- PARSE_ERROR;
-
- /* comma */
- if (!Parse_String(s, ","))
- PARSE_ERROR;
-
- /* second src arg */
- if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
- PARSE_ERROR;
-
- /* semicolon */
- if (!Parse_String(s, ";"))
- PARSE_ERROR;
-
- /* make sure we don't reference more than one program parameter register */
- if (IsProgRegister(inst->SrcReg[0].Register) &&
- IsProgRegister(inst->SrcReg[1].Register) &&
- inst->SrcReg[0].Register != inst->SrcReg[1].Register)
- PARSE_ERROR1("Can't reference two program parameter registers");
-
- /* make sure we don't reference more than one vertex attribute register */
- if (IsInputRegister(inst->SrcReg[0].Register) &&
- IsInputRegister(inst->SrcReg[1].Register) &&
- inst->SrcReg[0].Register != inst->SrcReg[1].Register)
- PARSE_ERROR1("Can't reference two vertex attribute registers");
-
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_TriOpInstruction(const GLubyte **s, struct vp_instruction *inst)
- {
- GLubyte token[100];
-
- /* opcode */
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (StrEq(token, (GLubyte *) "MAD")) {
- inst->Opcode = MAD;
- }
- else {
- PARSE_ERROR;
- }
-
- /* dest reg */
- if (!Parse_MaskedDstReg(s, &inst->DstReg))
- PARSE_ERROR;
-
- /* comma */
- if (!Parse_String(s, ","))
- PARSE_ERROR;
-
- /* first src arg */
- if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
- PARSE_ERROR;
-
- /* comma */
- if (!Parse_String(s, ","))
- PARSE_ERROR;
-
- /* second src arg */
- if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
- PARSE_ERROR;
-
- /* comma */
- if (!Parse_String(s, ","))
- PARSE_ERROR;
-
- /* third src arg */
- if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[2]))
- PARSE_ERROR;
-
- /* semicolon */
- if (!Parse_String(s, ";"))
- PARSE_ERROR;
-
- /* make sure we don't reference more than one program parameter register */
- if ((IsProgRegister(inst->SrcReg[0].Register) &&
- IsProgRegister(inst->SrcReg[1].Register) &&
- inst->SrcReg[0].Register != inst->SrcReg[1].Register) ||
- (IsProgRegister(inst->SrcReg[0].Register) &&
- IsProgRegister(inst->SrcReg[2].Register) &&
- inst->SrcReg[0].Register != inst->SrcReg[2].Register) ||
- (IsProgRegister(inst->SrcReg[1].Register) &&
- IsProgRegister(inst->SrcReg[2].Register) &&
- inst->SrcReg[1].Register != inst->SrcReg[2].Register))
- PARSE_ERROR1("Can only reference one program register");
-
- /* make sure we don't reference more than one vertex attribute register */
- if ((IsInputRegister(inst->SrcReg[0].Register) &&
- IsInputRegister(inst->SrcReg[1].Register) &&
- inst->SrcReg[0].Register != inst->SrcReg[1].Register) ||
- (IsInputRegister(inst->SrcReg[0].Register) &&
- IsInputRegister(inst->SrcReg[2].Register) &&
- inst->SrcReg[0].Register != inst->SrcReg[2].Register) ||
- (IsInputRegister(inst->SrcReg[1].Register) &&
- IsInputRegister(inst->SrcReg[2].Register) &&
- inst->SrcReg[1].Register != inst->SrcReg[2].Register))
- PARSE_ERROR1("Can only reference one input register");
-
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_ScalarInstruction(const GLubyte **s, struct vp_instruction *inst)
- {
- GLubyte token[100];
-
- /* opcode */
- if (!Parse_Token(s, token))
- PARSE_ERROR;
-
- if (StrEq(token, (GLubyte *) "RCP")) {
- inst->Opcode = RCP;
- }
- else if (StrEq(token, (GLubyte *) "RSQ")) {
- inst->Opcode = RSQ;
- }
- else if (StrEq(token, (GLubyte *) "EXP")) {
- inst->Opcode = EXP;
- }
- else if (StrEq(token, (GLubyte *) "LOG")) {
- inst->Opcode = LOG;
- }
- else if (StrEq(token, (GLubyte *) "RCC") && IsVersion1_1) {
- inst->Opcode = RCC;
- }
- else {
- PARSE_ERROR;
- }
-
- /* dest reg */
- if (!Parse_MaskedDstReg(s, &inst->DstReg))
- PARSE_ERROR;
-
- /* comma */
- if (!Parse_String(s, ","))
- PARSE_ERROR;
-
- /* first src arg */
- if (!Parse_ScalarSrcReg(s, &inst->SrcReg[0]))
- PARSE_ERROR;
-
- /* semicolon */
- if (!Parse_String(s, ";"))
- PARSE_ERROR;
-
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_AddressInstruction(const GLubyte **s, struct vp_instruction *inst)
- {
- inst->Opcode = ARL;
-
- /* opcode */
- if (!Parse_String(s, "ARL"))
- PARSE_ERROR;
-
- /* dest A0 reg */
- if (!Parse_AddrReg(s))
- PARSE_ERROR;
-
- /* comma */
- if (!Parse_String(s, ","))
- PARSE_ERROR;
-
- /* parse src reg */
- if (!Parse_ScalarSrcReg(s, &inst->SrcReg[0]))
- PARSE_ERROR;
-
- /* semicolon */
- if (!Parse_String(s, ";"))
- PARSE_ERROR;
-
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_EndInstruction(const GLubyte **s, struct vp_instruction *inst)
- {
- GLubyte token[100];
-
- /* opcode */
- if (!Parse_String(s, "END"))
- PARSE_ERROR;
-
- inst->Opcode = END;
-
- /* this should fail! */
- if (Parse_Token(s, token))
- PARSE_ERROR2("Unexpected token after END:", token);
- else
- return GL_TRUE;
- }
-
-
- static GLboolean
- Parse_OptionSequence(const GLubyte **s, struct vp_instruction program[])
- {
- while (1) {
- GLubyte token[100];
- if (!Peek_Token(s, token)) {
- PARSE_ERROR1("Unexpected end of input");
- return GL_FALSE; /* end of input */
- }
-
- if (!StrEq(token, (GLubyte *) "OPTION"))
- return GL_TRUE; /* probably an instruction */
-
- Parse_Token(s, token);
-
- if (!Parse_String(s, "NV_position_invariant"))
- return GL_FALSE;
- if (!Parse_String(s, ";"))
- return GL_FALSE;
- IsPositionInvariant = GL_TRUE;
- }
- }
-
-
- static GLboolean
- Parse_InstructionSequence(const GLubyte **s, struct vp_instruction program[])
- {
- GLubyte token[100];
- GLint count = 0;
-
- while (1) {
- struct vp_instruction *inst = program + count;
-
- /* Initialize the instruction */
- inst->SrcReg[0].Register = -1;
- inst->SrcReg[1].Register = -1;
- inst->SrcReg[2].Register = -1;
- inst->DstReg.Register = -1;
-
- if (!Peek_Token(s, token))
- PARSE_ERROR;
-
- if (StrEq(token, (GLubyte *) "MOV") ||
- StrEq(token, (GLubyte *) "LIT") ||
- StrEq(token, (GLubyte *) "ABS")) {
- if (!Parse_UnaryOpInstruction(s, inst))
- PARSE_ERROR;
- }
- else if (StrEq(token, (GLubyte *) "MUL") ||
- StrEq(token, (GLubyte *) "ADD") ||
- StrEq(token, (GLubyte *) "DP3") ||
- StrEq(token, (GLubyte *) "DP4") ||
- StrEq(token, (GLubyte *) "DST") ||
- StrEq(token, (GLubyte *) "MIN") ||
- StrEq(token, (GLubyte *) "MAX") ||
- StrEq(token, (GLubyte *) "SLT") ||
- StrEq(token, (GLubyte *) "SGE") ||
- StrEq(token, (GLubyte *) "DPH") ||
- StrEq(token, (GLubyte *) "SUB")) {
- if (!Parse_BiOpInstruction(s, inst))
- PARSE_ERROR;
- }
- else if (StrEq(token, (GLubyte *) "MAD")) {
- if (!Parse_TriOpInstruction(s, inst))
- PARSE_ERROR;
- }
- else if (StrEq(token, (GLubyte *) "RCP") ||
- StrEq(token, (GLubyte *) "RSQ") ||
- StrEq(token, (GLubyte *) "EXP") ||
- StrEq(token, (GLubyte *) "LOG") ||
- StrEq(token, (GLubyte *) "RCC")) {
- if (!Parse_ScalarInstruction(s, inst))
- PARSE_ERROR;
- }
- else if (StrEq(token, (GLubyte *) "ARL")) {
- if (!Parse_AddressInstruction(s, inst))
- PARSE_ERROR;
- }
- else if (StrEq(token, (GLubyte *) "END")) {
- if (!Parse_EndInstruction(s, inst))
- PARSE_ERROR;
- else
- return GL_TRUE; /* all done */
- }
- else {
- /* bad instruction name */
- PARSE_ERROR2("Unexpected token: ", token);
- }
-
- count++;
- if (count >= VP_MAX_INSTRUCTIONS)
- PARSE_ERROR1("Program too long");
- }
-
- PARSE_ERROR;
- }
-
-
- static GLboolean
- Parse_Program(const GLubyte **s, struct vp_instruction instBuffer[])
- {
- if (IsVersion1_1) {
- if (!Parse_OptionSequence(s, instBuffer)) {
- return GL_FALSE;
- }
- }
- return Parse_InstructionSequence(s, instBuffer);
- }
-
-
- /**
- * Parse/compile the 'str' returning the compiled 'program'.
- * ctx->VertexProgram.ErrorPos will be -1 if successful. Otherwise, ErrorPos
- * indicates the position of the error in 'str'.
- */
- void
- _mesa_parse_vertex_program(GLcontext *ctx, GLenum dstTarget,
- const GLubyte *str, GLsizei len,
- struct vp_program *program)
- {
- const GLubyte *s;
- struct vp_instruction instBuffer[VP_MAX_INSTRUCTIONS];
- GLubyte *newString;
- struct vp_instruction *newInst;
- GLenum target;
-
- ctx->VertexProgram.ErrorPos = -1;
- IsPositionInvariant = GL_FALSE;
- IsVersion1_1 = GL_FALSE;
-
- /* check the program header */
- if (_mesa_strncmp((const char *) str, "!!VP1.0", 7) == 0) {
- target = GL_VERTEX_PROGRAM_NV;
- s = str + 7;
- IsStateProgram = GL_FALSE;
- }
- else if (_mesa_strncmp((const char *) str, "!!VP1.1", 7) == 0) {
- target = GL_VERTEX_PROGRAM_NV;
- s = str + 7;
- IsStateProgram = GL_FALSE;
- IsVersion1_1 = GL_TRUE;
- }
- else if (_mesa_strncmp((const char *) str, "!!VSP1.0", 8) == 0) {
- target = GL_VERTEX_STATE_PROGRAM_NV;
- s = str + 8;
- IsStateProgram = GL_TRUE;
- }
- else {
- /* invalid header */
- ctx->VertexProgram.ErrorPos = 0;
- _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
- return;
- }
-
- /* make sure target and header match */
- if (target != dstTarget) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glLoadProgramNV(target mismatch)");
- return;
- }
-
- if (Parse_Program(&s, instBuffer)) {
- GLuint numInst;
- GLuint strLen;
- GLuint inputsRead = 0;
- GLuint outputsWritten = 0;
- GLuint progRegsWritten = 0;
-
- /* Find length of the program and compute bitmasks to indicate which
- * vertex input registers are read, which vertex result registers are
- * written to, and which program registers are written to.
- * We could actually do this while we parse the program.
- */
- for (numInst = 0; instBuffer[numInst].Opcode != END; numInst++) {
- const GLint srcReg0 = instBuffer[numInst].SrcReg[0].Register;
- const GLint srcReg1 = instBuffer[numInst].SrcReg[1].Register;
- const GLint srcReg2 = instBuffer[numInst].SrcReg[2].Register;
- const GLint dstReg = instBuffer[numInst].DstReg.Register;
-
- if (IsOutputRegister(dstReg))
- outputsWritten |= (1 << (dstReg - VP_OUTPUT_REG_START));
- else if (IsProgRegister(dstReg))
- progRegsWritten |= (1 << (dstReg - VP_PROG_REG_START));
- if (IsInputRegister(srcReg0)
- && !instBuffer[numInst].SrcReg[0].RelAddr)
- inputsRead |= (1 << (srcReg0 - VP_INPUT_REG_START));
- if (IsInputRegister(srcReg1)
- && !instBuffer[numInst].SrcReg[1].RelAddr)
- inputsRead |= (1 << (srcReg1 - VP_INPUT_REG_START));
- if (IsInputRegister(srcReg2)
- && !instBuffer[numInst].SrcReg[2].RelAddr)
- inputsRead |= (1 << (srcReg2 - VP_INPUT_REG_START));
- }
- numInst++;
-
- if (IsStateProgram) {
- if (progRegsWritten == 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glLoadProgramNV(c[#] not written)");
- return;
- }
- }
- else {
- if (!IsPositionInvariant && !(outputsWritten & 1)) {
- /* bit 1 = HPOS register */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glLoadProgramNV(HPOS not written)");
- return;
- }
- }
-
- program->InputsRead = inputsRead;
- program->OutputsWritten = outputsWritten;
- program->IsPositionInvariant = IsPositionInvariant;
-
- /* make copy of the input program string */
- strLen = _mesa_strlen((const char *) str);
- newString = (GLubyte *) MALLOC(strLen + 1);
- if (!newString) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
- return;
- }
- MEMCPY(newString, str, strLen);
- newString[strLen] = 0; /* terminate */
-
- /* copy the compiled instructions */
- assert(numInst <= VP_MAX_INSTRUCTIONS);
- newInst = (struct vp_instruction *) MALLOC(numInst * sizeof(struct vp_instruction));
- if (!newInst) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
- return; /* out of memory */
- }
- MEMCPY(newInst, instBuffer, numInst * sizeof(struct vp_instruction));
-
- /* install the program */
- program->Target = target;
- if (program->String) {
- FREE(program->String);
- }
- program->String = newString;
- if (program->Instructions) {
- FREE(program->Instructions);
- }
- program->Instructions = newInst;
-
- #ifdef DEBUG_foo
- _mesa_printf("--- glLoadProgramNV result ---\n");
- _mesa_print_vertex_program(program);
- _mesa_printf("------------------------------\n");
- #endif
- }
- else {
- /* Error! */
- #ifdef DEBUG
- /* print a message showing the program line containing the error */
- ctx->VertexProgram.ErrorPos = s - str;
- {
- const GLubyte *p = str, *line = str;
- int lineNum = 1, statementNum = 1, column = 0;
- char errorLine[1000];
- int i;
- while (*p && p < s) { /* s is the error position */
- if (*p == '\n') {
- line = p + 1;
- lineNum++;
- column = 0;
- }
- else if (*p == ';') {
- statementNum++;
- }
- else
- column++;
- p++;
- }
- if (p) {
- /* Copy the line with the error into errorLine so we can null-
- * terminate it.
- */
- for (i = 0; line[i] != '\n' && line[i]; i++)
- errorLine[i] = (char) line[i];
- errorLine[i] = 0;
- }
- /*
- _mesa_debug("Error pos = %d (%c) col %d\n",
- ctx->VertexProgram.ErrorPos, *s, column);
- */
- _mesa_debug(ctx, "Vertex program error on line %2d: %s\n", lineNum, errorLine);
- _mesa_debug(ctx, " (statement %2d) near column %2d: ", statementNum, column+1);
- for (i = 0; i < column; i++)
- _mesa_debug(ctx, " ");
- _mesa_debug(ctx, "^\n");
- }
- #endif
- _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
- }
- }
-
-
- static void
- PrintSrcReg(const struct vp_src_register *src)
- {
- static const char comps[5] = "xyzw";
- if (src->Negate)
- _mesa_printf("-");
- if (src->RelAddr) {
- if (src->Register > 0)
- _mesa_printf("c[A0.x + %d]", src->Register);
- else if (src->Register < 0)
- _mesa_printf("c[A0.x - %d]", -src->Register);
- else
- _mesa_printf("c[A0.x]");
- }
- else if (src->Register >= VP_OUTPUT_REG_START
- && src->Register <= VP_OUTPUT_REG_END) {
- _mesa_printf("o[%s]", OutputRegisters[src->Register - VP_OUTPUT_REG_START]);
- }
- else if (src->Register >= VP_INPUT_REG_START
- && src->Register <= VP_INPUT_REG_END) {
- _mesa_printf("v[%s]", InputRegisters[src->Register - VP_INPUT_REG_START]);
- }
- else if (src->Register >= VP_PROG_REG_START
- && src->Register <= VP_PROG_REG_END) {
- _mesa_printf("c[%d]", src->Register - VP_PROG_REG_START);
- }
- else {
- _mesa_printf("R%d", src->Register - VP_TEMP_REG_START);
- }
-
- if (src->Swizzle[0] == src->Swizzle[1] &&
- src->Swizzle[0] == src->Swizzle[2] &&
- src->Swizzle[0] == src->Swizzle[3]) {
- _mesa_printf(".%c", comps[src->Swizzle[0]]);
- }
- else if (src->Swizzle[0] != 0 ||
- src->Swizzle[1] != 1 ||
- src->Swizzle[2] != 2 ||
- src->Swizzle[3] != 3) {
- _mesa_printf(".%c%c%c%c",
- comps[src->Swizzle[0]],
- comps[src->Swizzle[1]],
- comps[src->Swizzle[2]],
- comps[src->Swizzle[3]]);
- }
- }
-
-
- static void
- PrintDstReg(const struct vp_dst_register *dst)
- {
- GLint w = dst->WriteMask[0] + dst->WriteMask[1]
- + dst->WriteMask[2] + dst->WriteMask[3];
-
- if (dst->Register >= VP_OUTPUT_REG_START
- && dst->Register <= VP_OUTPUT_REG_END) {
- _mesa_printf("o[%s]", OutputRegisters[dst->Register - VP_OUTPUT_REG_START]);
- }
- else if (dst->Register >= VP_INPUT_REG_START
- && dst->Register <= VP_INPUT_REG_END) {
- _mesa_printf("v[%s]", InputRegisters[dst->Register - VP_INPUT_REG_START]);
- }
- else if (dst->Register >= VP_PROG_REG_START
- && dst->Register <= VP_PROG_REG_END) {
- _mesa_printf("c[%d]", dst->Register - VP_PROG_REG_START);
- }
- else {
- _mesa_printf("R%d", dst->Register - VP_TEMP_REG_START);
- }
-
- if (w != 0 && w != 4) {
- _mesa_printf(".");
- if (dst->WriteMask[0])
- _mesa_printf("x");
- if (dst->WriteMask[1])
- _mesa_printf("y");
- if (dst->WriteMask[2])
- _mesa_printf("z");
- if (dst->WriteMask[3])
- _mesa_printf("w");
- }
- }
-
-
- /**
- * Print (unparse) the given vertex program. Just for debugging.
- */
- void
- _mesa_print_vertex_program(const struct vp_program *program)
- {
- const struct vp_instruction *inst;
-
- for (inst = program->Instructions; ; inst++) {
- switch (inst->Opcode) {
- case MOV:
- case LIT:
- case RCP:
- case RSQ:
- case EXP:
- case LOG:
- case RCC:
- case ABS:
- _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
- PrintDstReg(&inst->DstReg);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(";\n");
- break;
- case MUL:
- case ADD:
- case DP3:
- case DP4:
- case DST:
- case MIN:
- case MAX:
- case SLT:
- case SGE:
- case DPH:
- case SUB:
- _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
- PrintDstReg(&inst->DstReg);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[1]);
- _mesa_printf(";\n");
- break;
- case MAD:
- _mesa_printf("MAD ");
- PrintDstReg(&inst->DstReg);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[1]);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[2]);
- _mesa_printf(";\n");
- break;
- case ARL:
- _mesa_printf("ARL A0.x, ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(";\n");
- break;
- case END:
- _mesa_printf("END\n");
- return;
- break;
- default:
- _mesa_printf("BAD INSTRUCTION\n");
- }
- }
- }
-
-