113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/*
213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Mesa 3-D graphics library
3f4361540f8dd3016571523863b33481cba7a0c07Brian Paul * Version:  7.3
413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian *
5f4361540f8dd3016571523863b33481cba7a0c07Brian Paul * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian *
713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Permission is hereby granted, free of charge, to any person obtaining a
813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * copy of this software and associated documentation files (the "Software"),
913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * to deal in the Software without restriction, including without limitation
1013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * and/or sell copies of the Software, and to permit persons to whom the
1213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Software is furnished to do so, subject to the following conditions:
1313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian *
1413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * The above copyright notice and this permission notice shall be included
1513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * in all copies or substantial portions of the Software.
1613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian *
1713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
2413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
2513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
2613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * \file prog_execute.c
2713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Software interpreter for vertex/fragment programs.
2813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * \author Brian Paul
2913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
3013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
3113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/*
3213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * NOTE: we do everything in single-precision floating point; we don't
3313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * currently observe the single/half/fixed-precision qualifiers.
3413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian *
3513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
3613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
3713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
38bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/glheader.h"
39bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/colormac.h"
403fdd9fa556e9ba48244cb2b3966d3bfb0b84731bVinson Lee#include "main/macros.h"
4113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian#include "prog_execute.h"
4213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian#include "prog_instruction.h"
4313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian#include "prog_parameter.h"
4413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian#include "prog_print.h"
45702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "prog_noise.h"
4613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
4713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
4813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/* debug predicate */
4913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian#define DEBUG_PROG 0
5013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
5113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
52f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian/**
53f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian * Set x to positive or negative infinity.
54f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian */
55f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#if defined(USE_IEEE) || defined(_WIN32)
5672362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger#define SET_POS_INFINITY(x)                  \
5772362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger   do {                                      \
5872362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger         fi_type fi;                         \
5972362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger         fi.i = 0x7F800000;                  \
6072362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger         x = fi.f;                           \
6172362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger   } while (0)
6272362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger#define SET_NEG_INFINITY(x)                  \
6372362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger   do {                                      \
6472362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger         fi_type fi;                         \
6572362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger         fi.i = 0xFF800000;                  \
6672362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger         x = fi.f;                           \
6772362a5cd41d97b770980c28fe6719c556f12ab7Roland Scheidegger   } while (0)
68f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#elif defined(VMS)
69f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#define SET_POS_INFINITY(x)  x = __MAXFLOAT
70f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#define SET_NEG_INFINITY(x)  x = -__MAXFLOAT
71f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#else
72f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#define SET_POS_INFINITY(x)  x = (GLfloat) HUGE_VAL
73f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#define SET_NEG_INFINITY(x)  x = (GLfloat) -HUGE_VAL
74f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#endif
75f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian
76f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#define SET_FLOAT_BITS(x, bits) ((fi_type *) (void *) &(x))->i = bits
77f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian
78f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian
79f183a2d7ea31a4fea89af834dc19c5b232eb1970Brianstatic const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
80f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian
81f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian
82f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian
8313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
84b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul * Return TRUE for +0 and other positive values, FALSE otherwise.
85b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul * Used for RCC opcode.
86b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul */
879520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLboolean
88b4ad7c28430e4084d843cd99cf68209e95363963Brian Paulpositive(float x)
89b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul{
90b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul   fi_type fi;
91b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul   fi.f = x;
92b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul   if (fi.i & 0x80000000)
93b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul      return GL_FALSE;
94b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul   return GL_TRUE;
95b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul}
96b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul
97b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul
98b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul
99b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul/**
10013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Return a pointer to the 4-element float vector specified by the given
10113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * source register.
10213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
1039520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline const GLfloat *
104f4361540f8dd3016571523863b33481cba7a0c07Brian Paulget_src_register_pointer(const struct prog_src_register *source,
105f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                         const struct gl_program_machine *machine)
10613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian{
107f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   const struct gl_program *prog = machine->CurProgram;
108f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   GLint reg = source->Index;
109f4361540f8dd3016571523863b33481cba7a0c07Brian Paul
110f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian   if (source->RelAddr) {
111f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      /* add address register value to src index/offset */
112f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      reg += machine->AddressReg[0][0];
113f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (reg < 0) {
114f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return ZeroVec;
115f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian      }
116f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian   }
117f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian
11813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   switch (source->File) {
11913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case PROGRAM_TEMPORARY:
120f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (reg >= MAX_PROGRAM_TEMPS)
121f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return ZeroVec;
122f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      return machine->Temporaries[reg];
12313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
12413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case PROGRAM_INPUT:
125f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
126f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (reg >= VERT_ATTRIB_MAX)
127f4361540f8dd3016571523863b33481cba7a0c07Brian Paul            return ZeroVec;
128f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return machine->VertAttribs[reg];
12913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
13013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      else {
131f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (reg >= FRAG_ATTRIB_MAX)
132f4361540f8dd3016571523863b33481cba7a0c07Brian Paul            return ZeroVec;
133f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return machine->Attribs[reg][machine->CurElement];
13413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
13513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
13613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case PROGRAM_OUTPUT:
137f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (reg >= MAX_PROGRAM_OUTPUTS)
138f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return ZeroVec;
139f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      return machine->Outputs[reg];
14013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
14113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case PROGRAM_LOCAL_PARAM:
142f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (reg >= MAX_PROGRAM_LOCAL_PARAMS)
143f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return ZeroVec;
144f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      return machine->CurProgram->LocalParams[reg];
14513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
14613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case PROGRAM_ENV_PARAM:
147f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (reg >= MAX_PROGRAM_ENV_PARAMS)
148f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return ZeroVec;
149f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      return machine->EnvParams[reg];
15013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
15113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case PROGRAM_STATE_VAR:
15213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      /* Fallthrough */
15313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case PROGRAM_CONSTANT:
15413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      /* Fallthrough */
15513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case PROGRAM_UNIFORM:
15613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      /* Fallthrough */
15713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case PROGRAM_NAMED_PARAM:
158f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (reg >= (GLint) prog->Parameters->NumParameters)
159f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return ZeroVec;
1606d89abadbcd68bbe9e08f041412549f8dc1fc73cBryan Cain      return (GLfloat *) prog->Parameters->ParameterValues[reg];
161f4361540f8dd3016571523863b33481cba7a0c07Brian Paul
1626a0d3b7696260f449a1d0c5222814568764e8110Brian Paul   case PROGRAM_SYSTEM_VALUE:
1636a0d3b7696260f449a1d0c5222814568764e8110Brian Paul      assert(reg < Elements(machine->SystemValues));
1646a0d3b7696260f449a1d0c5222814568764e8110Brian Paul      return machine->SystemValues[reg];
1656a0d3b7696260f449a1d0c5222814568764e8110Brian Paul
166f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   default:
167f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      _mesa_problem(NULL,
168f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         "Invalid src register file %d in get_src_register_pointer()",
169f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         source->File);
170f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      return NULL;
171f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   }
172f4361540f8dd3016571523863b33481cba7a0c07Brian Paul}
173f4361540f8dd3016571523863b33481cba7a0c07Brian Paul
174f4361540f8dd3016571523863b33481cba7a0c07Brian Paul
175f4361540f8dd3016571523863b33481cba7a0c07Brian Paul/**
176f4361540f8dd3016571523863b33481cba7a0c07Brian Paul * Return a pointer to the 4-element float vector specified by the given
177f4361540f8dd3016571523863b33481cba7a0c07Brian Paul * destination register.
178f4361540f8dd3016571523863b33481cba7a0c07Brian Paul */
1799520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat *
180f4361540f8dd3016571523863b33481cba7a0c07Brian Paulget_dst_register_pointer(const struct prog_dst_register *dest,
181f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                         struct gl_program_machine *machine)
182f4361540f8dd3016571523863b33481cba7a0c07Brian Paul{
183f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   static GLfloat dummyReg[4];
184f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   GLint reg = dest->Index;
185f4361540f8dd3016571523863b33481cba7a0c07Brian Paul
186f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   if (dest->RelAddr) {
187f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      /* add address register value to src index/offset */
188f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      reg += machine->AddressReg[0][0];
189f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (reg < 0) {
190f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return dummyReg;
191f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      }
192f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   }
193f4361540f8dd3016571523863b33481cba7a0c07Brian Paul
194f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   switch (dest->File) {
195f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   case PROGRAM_TEMPORARY:
196f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (reg >= MAX_PROGRAM_TEMPS)
197f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return dummyReg;
198f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      return machine->Temporaries[reg];
199f4361540f8dd3016571523863b33481cba7a0c07Brian Paul
200f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   case PROGRAM_OUTPUT:
201f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      if (reg >= MAX_PROGRAM_OUTPUTS)
202f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         return dummyReg;
203f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      return machine->Outputs[reg];
204f4361540f8dd3016571523863b33481cba7a0c07Brian Paul
205f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   case PROGRAM_WRITE_ONLY:
206f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      return dummyReg;
20713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
20813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   default:
20933eac56e4a48143aa8acd5757feb68570e860de5Brian      _mesa_problem(NULL,
210f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         "Invalid dest register file %d in get_dst_register_pointer()",
211f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         dest->File);
21213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      return NULL;
21313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
21413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian}
21513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
21613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
217f4361540f8dd3016571523863b33481cba7a0c07Brian Paul
21813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
21913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Fetch a 4-element float vector from the given source register.
22013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Apply swizzling and negating as needed.
22113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
22213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brianstatic void
22333eac56e4a48143aa8acd5757feb68570e860de5Brianfetch_vector4(const struct prog_src_register *source,
224e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian              const struct gl_program_machine *machine, GLfloat result[4])
22513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian{
226f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   const GLfloat *src = get_src_register_pointer(source, machine);
22713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   ASSERT(src);
22813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
22913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (source->Swizzle == SWIZZLE_NOOP) {
23013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      /* no swizzling */
23113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      COPY_4V(result, src);
23213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
23313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   else {
23413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      ASSERT(GET_SWZ(source->Swizzle, 0) <= 3);
23513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      ASSERT(GET_SWZ(source->Swizzle, 1) <= 3);
23613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      ASSERT(GET_SWZ(source->Swizzle, 2) <= 3);
23713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      ASSERT(GET_SWZ(source->Swizzle, 3) <= 3);
23813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[0] = src[GET_SWZ(source->Swizzle, 0)];
23913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[1] = src[GET_SWZ(source->Swizzle, 1)];
24013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[2] = src[GET_SWZ(source->Swizzle, 2)];
24113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[3] = src[GET_SWZ(source->Swizzle, 3)];
24213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
24313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
24413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (source->Abs) {
24513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[0] = FABSF(result[0]);
24613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[1] = FABSF(result[1]);
24713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[2] = FABSF(result[2]);
24813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[3] = FABSF(result[3]);
24913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
2507db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul   if (source->Negate) {
2517db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul      ASSERT(source->Negate == NEGATE_XYZW);
25213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[0] = -result[0];
25313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[1] = -result[1];
25413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[2] = -result[2];
25513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[3] = -result[3];
25613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
25792009543705918760df92abb0cbb8cad68875e72Brian Paul
25892009543705918760df92abb0cbb8cad68875e72Brian Paul#ifdef NAN_CHECK
25992009543705918760df92abb0cbb8cad68875e72Brian Paul   assert(!IS_INF_OR_NAN(result[0]));
26092009543705918760df92abb0cbb8cad68875e72Brian Paul   assert(!IS_INF_OR_NAN(result[0]));
26192009543705918760df92abb0cbb8cad68875e72Brian Paul   assert(!IS_INF_OR_NAN(result[0]));
26292009543705918760df92abb0cbb8cad68875e72Brian Paul   assert(!IS_INF_OR_NAN(result[0]));
26392009543705918760df92abb0cbb8cad68875e72Brian Paul#endif
26413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian}
26513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
26662da6a1b3e341e53981e2817595e0eea107fe6cbBrian
26713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
26837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul * Fetch a 4-element uint vector from the given source register.
26937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul * Apply swizzling but not negation/abs.
27037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul */
27137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paulstatic void
27237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paulfetch_vector4ui(const struct prog_src_register *source,
27337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul                const struct gl_program_machine *machine, GLuint result[4])
27437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul{
275f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   const GLuint *src = (GLuint *) get_src_register_pointer(source, machine);
27637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   ASSERT(src);
27737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
27837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   if (source->Swizzle == SWIZZLE_NOOP) {
27937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      /* no swizzling */
28037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      COPY_4V(result, src);
28137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   }
28237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   else {
28337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      ASSERT(GET_SWZ(source->Swizzle, 0) <= 3);
28437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      ASSERT(GET_SWZ(source->Swizzle, 1) <= 3);
28537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      ASSERT(GET_SWZ(source->Swizzle, 2) <= 3);
28637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      ASSERT(GET_SWZ(source->Swizzle, 3) <= 3);
28737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      result[0] = src[GET_SWZ(source->Swizzle, 0)];
28837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      result[1] = src[GET_SWZ(source->Swizzle, 1)];
28937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      result[2] = src[GET_SWZ(source->Swizzle, 2)];
29037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      result[3] = src[GET_SWZ(source->Swizzle, 3)];
29137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   }
29237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
2937db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul   /* Note: no Negate or Abs here */
29437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul}
29537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
29637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
29737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
29837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul/**
29962da6a1b3e341e53981e2817595e0eea107fe6cbBrian * Fetch the derivative with respect to X or Y for the given register.
30062da6a1b3e341e53981e2817595e0eea107fe6cbBrian * XXX this currently only works for fragment program input attribs.
30113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
30262da6a1b3e341e53981e2817595e0eea107fe6cbBrianstatic void
303f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergfetch_vector4_deriv(struct gl_context * ctx,
304e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                    const struct prog_src_register *source,
30562da6a1b3e341e53981e2817595e0eea107fe6cbBrian                    const struct gl_program_machine *machine,
30662da6a1b3e341e53981e2817595e0eea107fe6cbBrian                    char xOrY, GLfloat result[4])
30713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian{
30837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   if (source->File == PROGRAM_INPUT &&
30937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul       source->Index < (GLint) machine->NumDeriv) {
31062da6a1b3e341e53981e2817595e0eea107fe6cbBrian      const GLint col = machine->CurElement;
31162da6a1b3e341e53981e2817595e0eea107fe6cbBrian      const GLfloat w = machine->Attribs[FRAG_ATTRIB_WPOS][col][3];
31262da6a1b3e341e53981e2817595e0eea107fe6cbBrian      const GLfloat invQ = 1.0f / w;
31362da6a1b3e341e53981e2817595e0eea107fe6cbBrian      GLfloat deriv[4];
31413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
31513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (xOrY == 'X') {
31662da6a1b3e341e53981e2817595e0eea107fe6cbBrian         deriv[0] = machine->DerivX[source->Index][0] * invQ;
31762da6a1b3e341e53981e2817595e0eea107fe6cbBrian         deriv[1] = machine->DerivX[source->Index][1] * invQ;
31862da6a1b3e341e53981e2817595e0eea107fe6cbBrian         deriv[2] = machine->DerivX[source->Index][2] * invQ;
31962da6a1b3e341e53981e2817595e0eea107fe6cbBrian         deriv[3] = machine->DerivX[source->Index][3] * invQ;
32013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
32113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      else {
32262da6a1b3e341e53981e2817595e0eea107fe6cbBrian         deriv[0] = machine->DerivY[source->Index][0] * invQ;
32362da6a1b3e341e53981e2817595e0eea107fe6cbBrian         deriv[1] = machine->DerivY[source->Index][1] * invQ;
32462da6a1b3e341e53981e2817595e0eea107fe6cbBrian         deriv[2] = machine->DerivY[source->Index][2] * invQ;
32562da6a1b3e341e53981e2817595e0eea107fe6cbBrian         deriv[3] = machine->DerivY[source->Index][3] * invQ;
32613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
32762da6a1b3e341e53981e2817595e0eea107fe6cbBrian
32862da6a1b3e341e53981e2817595e0eea107fe6cbBrian      result[0] = deriv[GET_SWZ(source->Swizzle, 0)];
32962da6a1b3e341e53981e2817595e0eea107fe6cbBrian      result[1] = deriv[GET_SWZ(source->Swizzle, 1)];
33062da6a1b3e341e53981e2817595e0eea107fe6cbBrian      result[2] = deriv[GET_SWZ(source->Swizzle, 2)];
33162da6a1b3e341e53981e2817595e0eea107fe6cbBrian      result[3] = deriv[GET_SWZ(source->Swizzle, 3)];
33262da6a1b3e341e53981e2817595e0eea107fe6cbBrian
33362da6a1b3e341e53981e2817595e0eea107fe6cbBrian      if (source->Abs) {
33462da6a1b3e341e53981e2817595e0eea107fe6cbBrian         result[0] = FABSF(result[0]);
33562da6a1b3e341e53981e2817595e0eea107fe6cbBrian         result[1] = FABSF(result[1]);
33662da6a1b3e341e53981e2817595e0eea107fe6cbBrian         result[2] = FABSF(result[2]);
33762da6a1b3e341e53981e2817595e0eea107fe6cbBrian         result[3] = FABSF(result[3]);
33813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
3397db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul      if (source->Negate) {
3407db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul         ASSERT(source->Negate == NEGATE_XYZW);
34162da6a1b3e341e53981e2817595e0eea107fe6cbBrian         result[0] = -result[0];
34262da6a1b3e341e53981e2817595e0eea107fe6cbBrian         result[1] = -result[1];
34362da6a1b3e341e53981e2817595e0eea107fe6cbBrian         result[2] = -result[2];
34462da6a1b3e341e53981e2817595e0eea107fe6cbBrian         result[3] = -result[3];
34513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
34613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
34762da6a1b3e341e53981e2817595e0eea107fe6cbBrian   else {
34862da6a1b3e341e53981e2817595e0eea107fe6cbBrian      ASSIGN_4V(result, 0.0, 0.0, 0.0, 0.0);
34913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
35013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian}
35113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
35213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
35313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
35413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * As above, but only return result[0] element.
35513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
35613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brianstatic void
35733eac56e4a48143aa8acd5757feb68570e860de5Brianfetch_vector1(const struct prog_src_register *source,
358e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian              const struct gl_program_machine *machine, GLfloat result[4])
35913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian{
360f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   const GLfloat *src = get_src_register_pointer(source, machine);
36113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   ASSERT(src);
36213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
36313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   result[0] = src[GET_SWZ(source->Swizzle, 0)];
36413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
36513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (source->Abs) {
36613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[0] = FABSF(result[0]);
36713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
3687db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul   if (source->Negate) {
36913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      result[0] = -result[0];
37013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
37113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian}
37213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
37313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
3748d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paulstatic GLuint
3758d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paulfetch_vector1ui(const struct prog_src_register *source,
3768d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul                const struct gl_program_machine *machine)
3778d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul{
3788d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul   const GLuint *src = (GLuint *) get_src_register_pointer(source, machine);
379984b72ad5f47cda8e141dc38524f6a0598dcc541Brian Paul   return src[GET_SWZ(source->Swizzle, 0)];
3808d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul}
3818d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul
3828d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul
38313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
384999b55663a09d9669a9d14c5aadfa84e6dcba288Brian * Fetch texel from texture.  Use partial derivatives when possible.
385999b55663a09d9669a9d14c5aadfa84e6dcba288Brian */
3869520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
387f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergfetch_texel(struct gl_context *ctx,
388999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            const struct gl_program_machine *machine,
389999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            const struct prog_instruction *inst,
390999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            const GLfloat texcoord[4], GLfloat lodBias,
391999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            GLfloat color[4])
392999b55663a09d9669a9d14c5aadfa84e6dcba288Brian{
393ade508312c701ce89d3c2cd717994dbbabb4f207Brian Paul   const GLuint unit = machine->Samplers[inst->TexSrcUnit];
394ade508312c701ce89d3c2cd717994dbbabb4f207Brian Paul
395999b55663a09d9669a9d14c5aadfa84e6dcba288Brian   /* Note: we only have the right derivatives for fragment input attribs.
396999b55663a09d9669a9d14c5aadfa84e6dcba288Brian    */
397999b55663a09d9669a9d14c5aadfa84e6dcba288Brian   if (machine->NumDeriv > 0 &&
398999b55663a09d9669a9d14c5aadfa84e6dcba288Brian       inst->SrcReg[0].File == PROGRAM_INPUT &&
399999b55663a09d9669a9d14c5aadfa84e6dcba288Brian       inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + inst->TexSrcUnit) {
400999b55663a09d9669a9d14c5aadfa84e6dcba288Brian      /* simple texture fetch for which we should have derivatives */
401999b55663a09d9669a9d14c5aadfa84e6dcba288Brian      GLuint attr = inst->SrcReg[0].Index;
402999b55663a09d9669a9d14c5aadfa84e6dcba288Brian      machine->FetchTexelDeriv(ctx, texcoord,
403999b55663a09d9669a9d14c5aadfa84e6dcba288Brian                               machine->DerivX[attr],
404999b55663a09d9669a9d14c5aadfa84e6dcba288Brian                               machine->DerivY[attr],
405ade508312c701ce89d3c2cd717994dbbabb4f207Brian Paul                               lodBias, unit, color);
406999b55663a09d9669a9d14c5aadfa84e6dcba288Brian   }
407999b55663a09d9669a9d14c5aadfa84e6dcba288Brian   else {
408ade508312c701ce89d3c2cd717994dbbabb4f207Brian Paul      machine->FetchTexelLod(ctx, texcoord, lodBias, unit, color);
409999b55663a09d9669a9d14c5aadfa84e6dcba288Brian   }
410999b55663a09d9669a9d14c5aadfa84e6dcba288Brian}
411999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
412999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
413999b55663a09d9669a9d14c5aadfa84e6dcba288Brian/**
41413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Test value against zero and return GT, LT, EQ or UN if NaN.
41513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
4169520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLuint
417e80d901d9854b7c24a71fcd5a3377c33f408c8c0Briangenerate_cc(float value)
41813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian{
41913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (value != value)
420e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      return COND_UN;           /* NaN */
42113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (value > 0.0F)
42213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      return COND_GT;
42313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (value < 0.0F)
42413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      return COND_LT;
42513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   return COND_EQ;
42613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian}
42713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
42813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
42913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
43013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Test if the ccMaskRule is satisfied by the given condition code.
43113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Used to mask destination writes according to the current condition code.
43213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
4339520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLboolean
43413e3b21b16b14112b416f3ee5742fc7bd1b2d823Briantest_cc(GLuint condCode, GLuint ccMaskRule)
43513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian{
43613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   switch (ccMaskRule) {
43713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case COND_EQ: return (condCode == COND_EQ);
43813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case COND_NE: return (condCode != COND_EQ);
43913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case COND_LT: return (condCode == COND_LT);
44013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case COND_GE: return (condCode == COND_GT || condCode == COND_EQ);
44113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case COND_LE: return (condCode == COND_LT || condCode == COND_EQ);
44213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case COND_GT: return (condCode == COND_GT);
44313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case COND_TR: return GL_TRUE;
44413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   case COND_FL: return GL_FALSE;
44513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   default:      return GL_TRUE;
44613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
44713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian}
44813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
44913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
45013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
45113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Evaluate the 4 condition codes against a predicate and return GL_TRUE
45213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * or GL_FALSE to indicate result.
45313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
4549520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLboolean
45513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brianeval_condition(const struct gl_program_machine *machine,
45613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian               const struct prog_instruction *inst)
45713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian{
45813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   const GLuint swizzle = inst->DstReg.CondSwizzle;
45913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   const GLuint condMask = inst->DstReg.CondMask;
46013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
46113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian       test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
46213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian       test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
46313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian       test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
46413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      return GL_TRUE;
46513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
46613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   else {
46713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      return GL_FALSE;
46813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
46913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian}
47013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
47113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
47213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
47313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
47413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Store 4 floats into a register.  Observe the instructions saturate and
47513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * set-condition-code flags.
47613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
47713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brianstatic void
478e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brianstore_vector4(const struct prog_instruction *inst,
479e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian              struct gl_program_machine *machine, const GLfloat value[4])
48013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian{
481f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   const struct prog_dst_register *dstReg = &(inst->DstReg);
48213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   const GLboolean clamp = inst->SaturateMode == SATURATE_ZERO_ONE;
483f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   GLuint writeMask = dstReg->WriteMask;
48413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   GLfloat clampedValue[4];
485f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   GLfloat *dst = get_dst_register_pointer(dstReg, machine);
48613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
48713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian#if 0
48813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (value[0] > 1.0e10 ||
48913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian       IS_INF_OR_NAN(value[0]) ||
49013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian       IS_INF_OR_NAN(value[1]) ||
491e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian       IS_INF_OR_NAN(value[2]) || IS_INF_OR_NAN(value[3]))
49213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      printf("store %g %g %g %g\n", value[0], value[1], value[2], value[3]);
49313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian#endif
49413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
49513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (clamp) {
49613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      clampedValue[0] = CLAMP(value[0], 0.0F, 1.0F);
49713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      clampedValue[1] = CLAMP(value[1], 0.0F, 1.0F);
49813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      clampedValue[2] = CLAMP(value[2], 0.0F, 1.0F);
49913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      clampedValue[3] = CLAMP(value[3], 0.0F, 1.0F);
50013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      value = clampedValue;
50113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
50213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
503f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   if (dstReg->CondMask != COND_TR) {
50413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      /* condition codes may turn off some writes */
50513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (writeMask & WRITEMASK_X) {
506f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 0)],
507f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                      dstReg->CondMask))
50813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            writeMask &= ~WRITEMASK_X;
50913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
51013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (writeMask & WRITEMASK_Y) {
511f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 1)],
512f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                      dstReg->CondMask))
51313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            writeMask &= ~WRITEMASK_Y;
51413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
51513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (writeMask & WRITEMASK_Z) {
516f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 2)],
517f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                      dstReg->CondMask))
51813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            writeMask &= ~WRITEMASK_Z;
51913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
52013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (writeMask & WRITEMASK_W) {
521f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 3)],
522f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                      dstReg->CondMask))
52313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            writeMask &= ~WRITEMASK_W;
52413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
52513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
52613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
52792009543705918760df92abb0cbb8cad68875e72Brian Paul#ifdef NAN_CHECK
52892009543705918760df92abb0cbb8cad68875e72Brian Paul   assert(!IS_INF_OR_NAN(value[0]));
52992009543705918760df92abb0cbb8cad68875e72Brian Paul   assert(!IS_INF_OR_NAN(value[0]));
53092009543705918760df92abb0cbb8cad68875e72Brian Paul   assert(!IS_INF_OR_NAN(value[0]));
53192009543705918760df92abb0cbb8cad68875e72Brian Paul   assert(!IS_INF_OR_NAN(value[0]));
53292009543705918760df92abb0cbb8cad68875e72Brian Paul#endif
53392009543705918760df92abb0cbb8cad68875e72Brian Paul
53413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (writeMask & WRITEMASK_X)
535f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      dst[0] = value[0];
53613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (writeMask & WRITEMASK_Y)
537f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      dst[1] = value[1];
53813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (writeMask & WRITEMASK_Z)
539f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      dst[2] = value[2];
54013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (writeMask & WRITEMASK_W)
541f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      dst[3] = value[3];
54213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
54313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (inst->CondUpdate) {
54413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (writeMask & WRITEMASK_X)
54513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian         machine->CondCodes[0] = generate_cc(value[0]);
54613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (writeMask & WRITEMASK_Y)
54713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian         machine->CondCodes[1] = generate_cc(value[1]);
54813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (writeMask & WRITEMASK_Z)
54913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian         machine->CondCodes[2] = generate_cc(value[2]);
55013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (writeMask & WRITEMASK_W)
55113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian         machine->CondCodes[3] = generate_cc(value[3]);
552a01616eed52aa4dfe3b6850b76a4cd8de119a3f3Brian#if DEBUG_PROG
553a01616eed52aa4dfe3b6850b76a4cd8de119a3f3Brian      printf("CondCodes=(%s,%s,%s,%s) for:\n",
554a01616eed52aa4dfe3b6850b76a4cd8de119a3f3Brian             _mesa_condcode_string(machine->CondCodes[0]),
555a01616eed52aa4dfe3b6850b76a4cd8de119a3f3Brian             _mesa_condcode_string(machine->CondCodes[1]),
556a01616eed52aa4dfe3b6850b76a4cd8de119a3f3Brian             _mesa_condcode_string(machine->CondCodes[2]),
557a01616eed52aa4dfe3b6850b76a4cd8de119a3f3Brian             _mesa_condcode_string(machine->CondCodes[3]));
558a01616eed52aa4dfe3b6850b76a4cd8de119a3f3Brian#endif
55913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
56013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian}
56113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
56213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
56313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian/**
56437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul * Store 4 uints into a register.  Observe the set-condition-code flags.
56537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul */
56637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paulstatic void
56737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paulstore_vector4ui(const struct prog_instruction *inst,
56837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul                struct gl_program_machine *machine, const GLuint value[4])
56937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul{
570f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   const struct prog_dst_register *dstReg = &(inst->DstReg);
571f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   GLuint writeMask = dstReg->WriteMask;
572f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   GLuint *dst = (GLuint *) get_dst_register_pointer(dstReg, machine);
57337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
574f4361540f8dd3016571523863b33481cba7a0c07Brian Paul   if (dstReg->CondMask != COND_TR) {
57537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      /* condition codes may turn off some writes */
57637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      if (writeMask & WRITEMASK_X) {
577f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 0)],
578f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                      dstReg->CondMask))
57937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            writeMask &= ~WRITEMASK_X;
58037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      }
58137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      if (writeMask & WRITEMASK_Y) {
582f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 1)],
583f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                      dstReg->CondMask))
58437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            writeMask &= ~WRITEMASK_Y;
58537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      }
58637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      if (writeMask & WRITEMASK_Z) {
587f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 2)],
588f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                      dstReg->CondMask))
58937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            writeMask &= ~WRITEMASK_Z;
59037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      }
59137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      if (writeMask & WRITEMASK_W) {
592f4361540f8dd3016571523863b33481cba7a0c07Brian Paul         if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 3)],
593f4361540f8dd3016571523863b33481cba7a0c07Brian Paul                      dstReg->CondMask))
59437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            writeMask &= ~WRITEMASK_W;
59537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      }
59637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   }
59737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
59837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   if (writeMask & WRITEMASK_X)
599f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      dst[0] = value[0];
60037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   if (writeMask & WRITEMASK_Y)
601f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      dst[1] = value[1];
60237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   if (writeMask & WRITEMASK_Z)
603f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      dst[2] = value[2];
60437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   if (writeMask & WRITEMASK_W)
605f4361540f8dd3016571523863b33481cba7a0c07Brian Paul      dst[3] = value[3];
60637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
60737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   if (inst->CondUpdate) {
60837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      if (writeMask & WRITEMASK_X)
609b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz         machine->CondCodes[0] = generate_cc((float)value[0]);
61037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      if (writeMask & WRITEMASK_Y)
611b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz         machine->CondCodes[1] = generate_cc((float)value[1]);
61237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      if (writeMask & WRITEMASK_Z)
613b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz         machine->CondCodes[2] = generate_cc((float)value[2]);
61437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      if (writeMask & WRITEMASK_W)
615b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz         machine->CondCodes[3] = generate_cc((float)value[3]);
61637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul#if DEBUG_PROG
61737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      printf("CondCodes=(%s,%s,%s,%s) for:\n",
61837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul             _mesa_condcode_string(machine->CondCodes[0]),
61937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul             _mesa_condcode_string(machine->CondCodes[1]),
62037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul             _mesa_condcode_string(machine->CondCodes[2]),
62137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul             _mesa_condcode_string(machine->CondCodes[3]));
62237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul#endif
62337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul   }
62437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul}
62537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
62637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
62737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul
62837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul/**
62913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * Execute the given vertex/fragment program.
63013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian *
6313c1c999226859216b8af35c4806413b4488f21b4Brian * \param ctx  rendering context
6323c1c999226859216b8af35c4806413b4488f21b4Brian * \param program  the program to execute
6333c1c999226859216b8af35c4806413b4488f21b4Brian * \param machine  machine state (must be initialized)
63413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian * \return GL_TRUE if program completed or GL_FALSE if program executed KIL.
63513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian */
63613e3b21b16b14112b416f3ee5742fc7bd1b2d823BrianGLboolean
637f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_execute_program(struct gl_context * ctx,
6388b34b7da4131d2b07037ce062c522fddd614f127Brian                      const struct gl_program *program,
639085d7d59f0e167bb546c4a1675e09631b14fc9f7Brian                      struct gl_program_machine *machine)
64013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian{
6418b34b7da4131d2b07037ce062c522fddd614f127Brian   const GLuint numInst = program->NumInstructions;
6427125f1e87df359be4aad1d801b633146eeac7292Ian Romanick   const GLuint maxExec = 65536;
643452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca   GLuint pc, numExec = 0;
64413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
64513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   machine->CurProgram = program;
64613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
64713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   if (DEBUG_PROG) {
64813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      printf("execute program %u --------------------\n", program->Id);
64913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   }
65013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
65133eac56e4a48143aa8acd5757feb68570e860de5Brian   if (program->Target == GL_VERTEX_PROGRAM_ARB) {
65233eac56e4a48143aa8acd5757feb68570e860de5Brian      machine->EnvParams = ctx->VertexProgram.Parameters;
65333eac56e4a48143aa8acd5757feb68570e860de5Brian   }
65433eac56e4a48143aa8acd5757feb68570e860de5Brian   else {
65533eac56e4a48143aa8acd5757feb68570e860de5Brian      machine->EnvParams = ctx->FragmentProgram.Parameters;
65633eac56e4a48143aa8acd5757feb68570e860de5Brian   }
65733eac56e4a48143aa8acd5757feb68570e860de5Brian
6588b34b7da4131d2b07037ce062c522fddd614f127Brian   for (pc = 0; pc < numInst; pc++) {
65913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      const struct prog_instruction *inst = program->Instructions + pc;
66013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
66113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      if (DEBUG_PROG) {
66213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian         _mesa_print_instruction(inst);
66313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
66413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
66513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      switch (inst->Opcode) {
666e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_ABS:
667e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
668e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
66933eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
670e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = FABSF(a[0]);
671e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = FABSF(a[1]);
672e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = FABSF(a[2]);
673e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = FABSF(a[3]);
674e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
675e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
676e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
677e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_ADD:
678e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
679e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
68033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
68133eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
682e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = a[0] + b[0];
683e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[1] + b[1];
684e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[2] + b[2];
685e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = a[3] + b[3];
686e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
687e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
688e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("ADD (%g %g %g %g) = (%g %g %g %g) + (%g %g %g %g)\n",
689e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], result[1], result[2], result[3],
690e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
69113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
692e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
693e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
69437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      case OPCODE_AND:     /* bitwise AND */
69537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         {
69637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLuint a[4], b[4], result[4];
69737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            fetch_vector4ui(&inst->SrcReg[0], machine, a);
69837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            fetch_vector4ui(&inst->SrcReg[1], machine, b);
69937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[0] = a[0] & b[0];
70037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[1] = a[1] & b[1];
70137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[2] = a[2] & b[2];
70237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[3] = a[3] & b[3];
70337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            store_vector4ui(inst, machine, result);
70437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         }
70537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         break;
706f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian      case OPCODE_ARL:
707f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian         {
708f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            GLfloat t[4];
70933eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, t);
710a9475cc240984aab5d9cc5868aa3f6c1b206be94Brian Paul            machine->AddressReg[0][0] = IFLOOR(t[0]);
711a636f5b4d064dccf658f00d152ae9aeaa3751e64Brian Paul            if (DEBUG_PROG) {
712a636f5b4d064dccf658f00d152ae9aeaa3751e64Brian Paul               printf("ARL %d\n", machine->AddressReg[0][0]);
713a636f5b4d064dccf658f00d152ae9aeaa3751e64Brian Paul            }
714f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian         }
715f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian         break;
716e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_BGNLOOP:
717e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         /* no-op */
718e8ea2d26cd9e90d45cdfb94c3a6b06e27d6c0083Brian Paul         ASSERT(program->Instructions[inst->BranchTarget].Opcode
719e8ea2d26cd9e90d45cdfb94c3a6b06e27d6c0083Brian Paul                == OPCODE_ENDLOOP);
720e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
721e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_ENDLOOP:
722e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         /* subtract 1 here since pc is incremented by for(pc) loop */
723e8ea2d26cd9e90d45cdfb94c3a6b06e27d6c0083Brian Paul         ASSERT(program->Instructions[inst->BranchTarget].Opcode
724e8ea2d26cd9e90d45cdfb94c3a6b06e27d6c0083Brian Paul                == OPCODE_BGNLOOP);
725e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         pc = inst->BranchTarget - 1;   /* go to matching BNGLOOP */
726e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
727e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_BGNSUB:      /* begin subroutine */
728e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
729e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_ENDSUB:      /* end subroutine */
730e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
731e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_BRA:         /* branch (conditional) */
732db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul         if (eval_condition(machine, inst)) {
733db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul            /* take branch */
734db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul            /* Subtract 1 here since we'll do pc++ below */
735db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul            pc = inst->BranchTarget - 1;
736db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul         }
737db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul         break;
738e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_BRK:         /* break out of loop (conditional) */
739db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul         ASSERT(program->Instructions[inst->BranchTarget].Opcode
740db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul                == OPCODE_ENDLOOP);
741db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul         if (eval_condition(machine, inst)) {
742db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul            /* break out of loop */
743db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul            /* pc++ at end of for-loop will put us after the ENDLOOP inst */
744db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul            pc = inst->BranchTarget;
745db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul         }
746db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul         break;
747e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_CONT:        /* continue loop (conditional) */
748db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul         ASSERT(program->Instructions[inst->BranchTarget].Opcode
749db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul                == OPCODE_ENDLOOP);
750e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         if (eval_condition(machine, inst)) {
751db721151b76611b75bcedfc90221ef5f92e8edebBrian Paul            /* continue at ENDLOOP */
752e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            /* Subtract 1 here since we'll do pc++ at end of for-loop */
753e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            pc = inst->BranchTarget - 1;
754e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
755e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
756e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_CAL:         /* Call subroutine (conditional) */
757e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         if (eval_condition(machine, inst)) {
758e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            /* call the subroutine */
759e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (machine->StackDepth >= MAX_PROGRAM_CALL_DEPTH) {
760e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               return GL_TRUE;  /* Per GL_NV_vertex_program2 spec */
761e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            }
762a0275b0d2c071ed8254c2af3a0c53eec9d3561a6Brian            machine->CallStack[machine->StackDepth++] = pc + 1; /* next inst */
76331dc7a3c890a831f9a0d20dc394ddbe854a05718Brian            /* Subtract 1 here since we'll do pc++ at end of for-loop */
76431dc7a3c890a831f9a0d20dc394ddbe854a05718Brian            pc = inst->BranchTarget - 1;
765e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
766e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
767e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_CMP:
768e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
769e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], c[4], result[4];
77033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
77133eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
77233eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[2], machine, c);
773e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = a[0] < 0.0F ? b[0] : c[0];
774e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[1] < 0.0F ? b[1] : c[1];
775e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[2] < 0.0F ? b[2] : c[2];
776e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = a[3] < 0.0F ? b[3] : c[3];
777e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
778fd7f2ae085ea55649089b29515e143eed43c177eBrian Paul            if (DEBUG_PROG) {
779fd7f2ae085ea55649089b29515e143eed43c177eBrian Paul               printf("CMP (%g %g %g %g) = (%g %g %g %g) < 0 ? (%g %g %g %g) : (%g %g %g %g)\n",
780fd7f2ae085ea55649089b29515e143eed43c177eBrian Paul                      result[0], result[1], result[2], result[3],
781fd7f2ae085ea55649089b29515e143eed43c177eBrian Paul                      a[0], a[1], a[2], a[3],
782fd7f2ae085ea55649089b29515e143eed43c177eBrian Paul                      b[0], b[1], b[2], b[3],
783fd7f2ae085ea55649089b29515e143eed43c177eBrian Paul                      c[0], c[1], c[2], c[3]);
784fd7f2ae085ea55649089b29515e143eed43c177eBrian Paul            }
785e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
786e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
787e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_COS:
788e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
789e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
79033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, a);
791e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = result[1] = result[2] = result[3]
792165694ad65374ff4330bd80acb398fe0428ba2e6Eric Anholt               = (GLfloat) cos(a[0]);
793e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
794e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
795e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
796e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_DDX:         /* Partial derivative with respect to X */
797e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
79862da6a1b3e341e53981e2817595e0eea107fe6cbBrian            GLfloat result[4];
79962da6a1b3e341e53981e2817595e0eea107fe6cbBrian            fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine,
80062da6a1b3e341e53981e2817595e0eea107fe6cbBrian                                'X', result);
801e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
802e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
803e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
804e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_DDY:         /* Partial derivative with respect to Y */
805e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
80662da6a1b3e341e53981e2817595e0eea107fe6cbBrian            GLfloat result[4];
80762da6a1b3e341e53981e2817595e0eea107fe6cbBrian            fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine,
80862da6a1b3e341e53981e2817595e0eea107fe6cbBrian                                'Y', result);
809e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
810e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
811e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
81265cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul      case OPCODE_DP2:
81365cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul         {
81465cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            GLfloat a[4], b[4], result[4];
81565cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            fetch_vector4(&inst->SrcReg[0], machine, a);
81665cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            fetch_vector4(&inst->SrcReg[1], machine, b);
81765cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            result[0] = result[1] = result[2] = result[3] = DOT2(a, b);
81865cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            store_vector4(inst, machine, result);
81965cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            if (DEBUG_PROG) {
82065cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul               printf("DP2 %g = (%g %g) . (%g %g)\n",
82165cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul                      result[0], a[0], a[1], b[0], b[1]);
82265cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            }
82365cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul         }
82465cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul         break;
82565cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul      case OPCODE_DP2A:
82665cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul         {
82765cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            GLfloat a[4], b[4], c, result[4];
82865cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            fetch_vector4(&inst->SrcReg[0], machine, a);
82965cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            fetch_vector4(&inst->SrcReg[1], machine, b);
83065cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            fetch_vector1(&inst->SrcReg[1], machine, &c);
83165cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            result[0] = result[1] = result[2] = result[3] = DOT2(a, b) + c;
83265cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            store_vector4(inst, machine, result);
83365cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            if (DEBUG_PROG) {
83465cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul               printf("DP2A %g = (%g %g) . (%g %g) + %g\n",
83565cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul                      result[0], a[0], a[1], b[0], b[1], c);
83665cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            }
83765cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul         }
83865cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul         break;
839e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_DP3:
840e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
841e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
84233eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
84333eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
844e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = result[1] = result[2] = result[3] = DOT3(a, b);
845e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
846e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
847e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("DP3 %g = (%g %g %g) . (%g %g %g)\n",
848e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], a[0], a[1], a[2], b[0], b[1], b[2]);
84913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
850e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
851e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
852e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_DP4:
853e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
854e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
85533eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
85633eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
857e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = result[1] = result[2] = result[3] = DOT4(a, b);
858e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
859e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
860e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n",
861e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], a[0], a[1], a[2], a[3],
862e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      b[0], b[1], b[2], b[3]);
86313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
864e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
865e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
866e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_DPH:
867e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
868e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
86933eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
87033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
87165cb74ecc0287d766493fd3649295e2e1b20099bBrian Paul            result[0] = result[1] = result[2] = result[3] = DOT3(a, b) + b[3];
872e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
873e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
874e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
875e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_DST:         /* Distance vector */
876e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
877e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
87833eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
87933eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
880e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = 1.0F;
881e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[1] * b[1];
882e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[2];
883e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = b[3];
884e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
885e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
886e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
887f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian      case OPCODE_EXP:
888f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian         {
889f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            GLfloat t[4], q[4], floor_t0;
89033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, t);
891f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            floor_t0 = FLOORF(t[0]);
892f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            if (floor_t0 > FLT_MAX_EXP) {
893f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               SET_POS_INFINITY(q[0]);
894f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               SET_POS_INFINITY(q[2]);
895f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            }
896f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            else if (floor_t0 < FLT_MIN_EXP) {
897f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               q[0] = 0.0F;
898f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               q[2] = 0.0F;
899f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            }
900f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            else {
901761728afe8b81fc0ff7928f99f8b5668a0a7824dBrian               q[0] = LDEXPF(1.0, (int) floor_t0);
902761728afe8b81fc0ff7928f99f8b5668a0a7824dBrian               /* Note: GL_NV_vertex_program expects
903761728afe8b81fc0ff7928f99f8b5668a0a7824dBrian                * result.z = result.x * APPX(result.y)
904761728afe8b81fc0ff7928f99f8b5668a0a7824dBrian                * We do what the ARB extension says.
905761728afe8b81fc0ff7928f99f8b5668a0a7824dBrian                */
906fef303bc94f2fb15a068563ac8abfb1765bde035Eric Anholt               q[2] = (GLfloat) pow(2.0, t[0]);
907f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            }
908f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            q[1] = t[0] - floor_t0;
909f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            q[3] = 1.0F;
910f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            store_vector4( inst, machine, q );
911f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian         }
912f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian         break;
913e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_EX2:         /* Exponential base 2 */
914e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
915035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            GLfloat a[4], result[4], val;
91633eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, a);
917fef303bc94f2fb15a068563ac8abfb1765bde035Eric Anholt            val = (GLfloat) pow(2.0, a[0]);
918035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            /*
919035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            if (IS_INF_OR_NAN(val))
920035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul               val = 1.0e10;
921035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            */
922035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            result[0] = result[1] = result[2] = result[3] = val;
923e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
924e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
925e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
926e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_FLR:
927e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
928e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
92933eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
930e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = FLOORF(a[0]);
931e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = FLOORF(a[1]);
932e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = FLOORF(a[2]);
933e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = FLOORF(a[3]);
934e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
935e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
936e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
937e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_FRC:
938e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
939e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
94033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
941e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = a[0] - FLOORF(a[0]);
942e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[1] - FLOORF(a[1]);
943e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[2] - FLOORF(a[2]);
944e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = a[3] - FLOORF(a[3]);
945e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
946e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
947e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
948e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_IF:
94963556fa9949f543a8134b6b5ff3d216acb71dd9fBrian         {
95063556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            GLboolean cond;
951ddd9729bc37f4b1098ef940da6e723743db3ded8Brian Paul            ASSERT(program->Instructions[inst->BranchTarget].Opcode
952ddd9729bc37f4b1098ef940da6e723743db3ded8Brian Paul                   == OPCODE_ELSE ||
953ddd9729bc37f4b1098ef940da6e723743db3ded8Brian Paul                   program->Instructions[inst->BranchTarget].Opcode
954ddd9729bc37f4b1098ef940da6e723743db3ded8Brian Paul                   == OPCODE_ENDIF);
95563556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            /* eval condition */
95663556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
95763556fa9949f543a8134b6b5ff3d216acb71dd9fBrian               GLfloat a[4];
95863556fa9949f543a8134b6b5ff3d216acb71dd9fBrian               fetch_vector1(&inst->SrcReg[0], machine, a);
95963556fa9949f543a8134b6b5ff3d216acb71dd9fBrian               cond = (a[0] != 0.0);
96063556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            }
96163556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            else {
96263556fa9949f543a8134b6b5ff3d216acb71dd9fBrian               cond = eval_condition(machine, inst);
96363556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            }
964a7f7366d382b2fe124f1495baf0360bffa30f0c0Brian            if (DEBUG_PROG) {
965a7f7366d382b2fe124f1495baf0360bffa30f0c0Brian               printf("IF: %d\n", cond);
966a7f7366d382b2fe124f1495baf0360bffa30f0c0Brian            }
96763556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            /* do if/else */
96863556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            if (cond) {
96963556fa9949f543a8134b6b5ff3d216acb71dd9fBrian               /* do if-clause (just continue execution) */
97063556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            }
97163556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            else {
97263556fa9949f543a8134b6b5ff3d216acb71dd9fBrian               /* go to the instruction after ELSE or ENDIF */
97363556fa9949f543a8134b6b5ff3d216acb71dd9fBrian               assert(inst->BranchTarget >= 0);
974ddd9729bc37f4b1098ef940da6e723743db3ded8Brian Paul               pc = inst->BranchTarget;
97563556fa9949f543a8134b6b5ff3d216acb71dd9fBrian            }
976e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
977e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
978e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_ELSE:
979e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         /* goto ENDIF */
980ddd9729bc37f4b1098ef940da6e723743db3ded8Brian Paul         ASSERT(program->Instructions[inst->BranchTarget].Opcode
981ddd9729bc37f4b1098ef940da6e723743db3ded8Brian Paul                == OPCODE_ENDIF);
982e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         assert(inst->BranchTarget >= 0);
983ddd9729bc37f4b1098ef940da6e723743db3ded8Brian Paul         pc = inst->BranchTarget;
984e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
985e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_ENDIF:
986e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         /* nothing */
987e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
988e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_KIL_NV:      /* NV_f_p only (conditional) */
989e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         if (eval_condition(machine, inst)) {
990e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            return GL_FALSE;
991e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
992e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
993e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_KIL:         /* ARB_f_p only */
994e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
995e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4];
99633eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
997c0633ddabbcc91dcf06fd4452eb7516c624752c0Brian Paul            if (DEBUG_PROG) {
998c0633ddabbcc91dcf06fd4452eb7516c624752c0Brian Paul               printf("KIL if (%g %g %g %g) <= 0.0\n",
999c0633ddabbcc91dcf06fd4452eb7516c624752c0Brian Paul                      a[0], a[1], a[2], a[3]);
1000c0633ddabbcc91dcf06fd4452eb7516c624752c0Brian Paul            }
1001c0633ddabbcc91dcf06fd4452eb7516c624752c0Brian Paul
1002e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (a[0] < 0.0F || a[1] < 0.0F || a[2] < 0.0F || a[3] < 0.0F) {
100313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian               return GL_FALSE;
100413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1005e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1006e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1007e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_LG2:         /* log base 2 */
1008e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1009035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            GLfloat a[4], result[4], val;
101033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, a);
1011962fa6bbc16abf2b9829bd0b761d9baa9d01fd1eIan Romanick	    /* The fast LOG2 macro doesn't meet the precision requirements.
1012962fa6bbc16abf2b9829bd0b761d9baa9d01fd1eIan Romanick	     */
1013035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            if (a[0] == 0.0F) {
101418883cdf2334511005973155fc517eb678dc0043Vinson Lee               val = -FLT_MAX;
1015035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            }
1016035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            else {
1017b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz               val = (float)(log(a[0]) * 1.442695F);
1018035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            }
1019035de6a82b6c911a81ca9c678aac59772eaff8d3Brian Paul            result[0] = result[1] = result[2] = result[3] = val;
1020e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1021e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1022e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1023e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_LIT:
1024e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1025e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            const GLfloat epsilon = 1.0F / 256.0F;      /* from NV VP spec */
1026e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
102733eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
1028e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[0] = MAX2(a[0], 0.0F);
1029e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[1] = MAX2(a[1], 0.0F);
1030e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            /* XXX ARB version clamps a[3], NV version doesn't */
1031e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[3] = CLAMP(a[3], -(128.0F - epsilon), (128.0F - epsilon));
1032e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = 1.0F;
1033e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[0];
1034e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            /* XXX we could probably just use pow() here */
1035e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (a[0] > 0.0F) {
1036e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               if (a[1] == 0.0 && a[3] == 0.0)
103720fbb24b67dda0679774756e4b6d98c2c66c2c42Brian Paul                  result[2] = 1.0F;
1038e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               else
1039fef303bc94f2fb15a068563ac8abfb1765bde035Eric Anholt                  result[2] = (GLfloat) pow(a[1], a[3]);
104013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1041e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            else {
104220fbb24b67dda0679774756e4b6d98c2c66c2c42Brian Paul               result[2] = 0.0F;
104313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1044e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = 1.0F;
1045e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1046e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1047e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("LIT (%g %g %g %g) : (%g %g %g %g)\n",
1048e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], result[1], result[2], result[3],
1049e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      a[0], a[1], a[2], a[3]);
105013e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1051e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1052e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1053f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian      case OPCODE_LOG:
1054f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian         {
1055f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            GLfloat t[4], q[4], abs_t0;
105633eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, t);
1057f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            abs_t0 = FABSF(t[0]);
1058f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            if (abs_t0 != 0.0F) {
1059f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               /* Since we really can't handle infinite values on VMS
1060f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                * like other OSes we'll use __MAXFLOAT to represent
1061f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                * infinity.  This may need some tweaking.
1062f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                */
1063f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#ifdef VMS
1064f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               if (abs_t0 == __MAXFLOAT)
1065f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#else
1066f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               if (IS_INF_OR_NAN(abs_t0))
1067f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian#endif
1068f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               {
1069f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                  SET_POS_INFINITY(q[0]);
1070f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                  q[1] = 1.0F;
1071f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                  SET_POS_INFINITY(q[2]);
1072f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               }
1073f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               else {
1074f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                  int exponent;
1075f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                  GLfloat mantissa = FREXPF(t[0], &exponent);
1076f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                  q[0] = (GLfloat) (exponent - 1);
1077f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian                  q[1] = (GLfloat) (2.0 * mantissa); /* map [.5, 1) -> [1, 2) */
1078962fa6bbc16abf2b9829bd0b761d9baa9d01fd1eIan Romanick
1079962fa6bbc16abf2b9829bd0b761d9baa9d01fd1eIan Romanick		  /* The fast LOG2 macro doesn't meet the precision
1080962fa6bbc16abf2b9829bd0b761d9baa9d01fd1eIan Romanick		   * requirements.
1081962fa6bbc16abf2b9829bd0b761d9baa9d01fd1eIan Romanick		   */
1082b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz                  q[2] = (float)(log(t[0]) * 1.442695F);
1083f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               }
1084f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            }
1085f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            else {
1086f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               SET_NEG_INFINITY(q[0]);
1087f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               q[1] = 1.0F;
1088f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian               SET_NEG_INFINITY(q[2]);
1089f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            }
1090f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            q[3] = 1.0;
1091f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian            store_vector4(inst, machine, q);
1092f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian         }
1093f183a2d7ea31a4fea89af834dc19c5b232eb1970Brian         break;
1094e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_LRP:
1095e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1096e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], c[4], result[4];
109733eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
109833eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
109933eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[2], machine, c);
1100e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = a[0] * b[0] + (1.0F - a[0]) * c[0];
1101e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[1] * b[1] + (1.0F - a[1]) * c[1];
1102e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[2] * b[2] + (1.0F - a[2]) * c[2];
1103e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = a[3] * b[3] + (1.0F - a[3]) * c[3];
1104e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1105e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1106e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("LRP (%g %g %g %g) = (%g %g %g %g), "
1107e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      "(%g %g %g %g), (%g %g %g %g)\n",
1108e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], result[1], result[2], result[3],
1109e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      a[0], a[1], a[2], a[3],
1110e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]);
111113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1112e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1113e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1114e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_MAD:
1115e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1116e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], c[4], result[4];
111733eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
111833eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
111933eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[2], machine, c);
1120e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = a[0] * b[0] + c[0];
1121e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[1] * b[1] + c[1];
1122e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[2] * b[2] + c[2];
1123e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = a[3] * b[3] + c[3];
1124e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1125e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1126e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("MAD (%g %g %g %g) = (%g %g %g %g) * "
1127e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      "(%g %g %g %g) + (%g %g %g %g)\n",
1128e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], result[1], result[2], result[3],
1129e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      a[0], a[1], a[2], a[3],
1130e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]);
113113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1132e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1133e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1134e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_MAX:
1135e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1136e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
113733eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
113833eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1139e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = MAX2(a[0], b[0]);
1140e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = MAX2(a[1], b[1]);
1141e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = MAX2(a[2], b[2]);
1142e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = MAX2(a[3], b[3]);
1143e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1144e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1145e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("MAX (%g %g %g %g) = (%g %g %g %g), (%g %g %g %g)\n",
1146e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], result[1], result[2], result[3],
1147e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
114813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1149e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1150e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1151e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_MIN:
1152e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1153e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
115433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
115533eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1156e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = MIN2(a[0], b[0]);
1157e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = MIN2(a[1], b[1]);
1158e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = MIN2(a[2], b[2]);
1159e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = MIN2(a[3], b[3]);
1160e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1161e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1162e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1163e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_MOV:
1164e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1165e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat result[4];
116633eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, result);
1167e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1168e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1169e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("MOV (%g %g %g %g)\n",
1170e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], result[1], result[2], result[3]);
117113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1172e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1173e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1174e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_MUL:
1175e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1176e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
117733eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
117833eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1179e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = a[0] * b[0];
1180e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[1] * b[1];
1181e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[2] * b[2];
1182e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = a[3] * b[3];
1183e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1184e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1185e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("MUL (%g %g %g %g) = (%g %g %g %g) * (%g %g %g %g)\n",
1186e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], result[1], result[2], result[3],
1187e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
118813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1189e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1190e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1191e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_NOISE1:
1192e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1193e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
119433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, a);
1195e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] =
119613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian               result[1] =
1197702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul               result[2] =
1198702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul               result[3] = _mesa_noise1(a[0]);
1199e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1200e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1201e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1202e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_NOISE2:
1203e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1204e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
120533eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
1206e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] =
120713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian               result[1] =
1208702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul               result[2] = result[3] = _mesa_noise2(a[0], a[1]);
1209e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1210e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1211e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1212e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_NOISE3:
1213e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1214e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
121533eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
1216e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] =
121713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian               result[1] =
121813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian               result[2] =
1219702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul               result[3] = _mesa_noise3(a[0], a[1], a[2]);
1220e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1221e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1222e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1223e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_NOISE4:
1224e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1225e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
122633eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
1227e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] =
122813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian               result[1] =
122913e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian               result[2] =
1230702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul               result[3] = _mesa_noise4(a[0], a[1], a[2], a[3]);
1231e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1232e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1233e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1234e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_NOP:
1235e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
123637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      case OPCODE_NOT:         /* bitwise NOT */
123737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         {
123837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLuint a[4], result[4];
123937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            fetch_vector4ui(&inst->SrcReg[0], machine, a);
124037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[0] = ~a[0];
124137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[1] = ~a[1];
124237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[2] = ~a[2];
124337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[3] = ~a[3];
124437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            store_vector4ui(inst, machine, result);
124537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         }
124637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         break;
1247f6ead50827c03017e6b730313c361b39190da92fBrian Paul      case OPCODE_NRM3:        /* 3-component normalization */
1248f6ead50827c03017e6b730313c361b39190da92fBrian Paul         {
1249f6ead50827c03017e6b730313c361b39190da92fBrian Paul            GLfloat a[4], result[4];
1250f6ead50827c03017e6b730313c361b39190da92fBrian Paul            GLfloat tmp;
1251f6ead50827c03017e6b730313c361b39190da92fBrian Paul            fetch_vector4(&inst->SrcReg[0], machine, a);
1252f6ead50827c03017e6b730313c361b39190da92fBrian Paul            tmp = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
1253f6ead50827c03017e6b730313c361b39190da92fBrian Paul            if (tmp != 0.0F)
125422459e7a9ca01cc5af8d9baeb6354d2e825cdbc9Brian Paul               tmp = INV_SQRTF(tmp);
1255f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[0] = tmp * a[0];
1256f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[1] = tmp * a[1];
1257f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[2] = tmp * a[2];
1258f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[3] = 0.0;  /* undefined, but prevent valgrind warnings */
1259f6ead50827c03017e6b730313c361b39190da92fBrian Paul            store_vector4(inst, machine, result);
1260f6ead50827c03017e6b730313c361b39190da92fBrian Paul         }
1261f6ead50827c03017e6b730313c361b39190da92fBrian Paul         break;
1262f6ead50827c03017e6b730313c361b39190da92fBrian Paul      case OPCODE_NRM4:        /* 4-component normalization */
1263f6ead50827c03017e6b730313c361b39190da92fBrian Paul         {
1264f6ead50827c03017e6b730313c361b39190da92fBrian Paul            GLfloat a[4], result[4];
1265f6ead50827c03017e6b730313c361b39190da92fBrian Paul            GLfloat tmp;
1266f6ead50827c03017e6b730313c361b39190da92fBrian Paul            fetch_vector4(&inst->SrcReg[0], machine, a);
1267f6ead50827c03017e6b730313c361b39190da92fBrian Paul            tmp = a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3];
1268f6ead50827c03017e6b730313c361b39190da92fBrian Paul            if (tmp != 0.0F)
126922459e7a9ca01cc5af8d9baeb6354d2e825cdbc9Brian Paul               tmp = INV_SQRTF(tmp);
1270f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[0] = tmp * a[0];
1271f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[1] = tmp * a[1];
1272f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[2] = tmp * a[2];
1273f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[3] = tmp * a[3];
1274f6ead50827c03017e6b730313c361b39190da92fBrian Paul            store_vector4(inst, machine, result);
1275f6ead50827c03017e6b730313c361b39190da92fBrian Paul         }
1276f6ead50827c03017e6b730313c361b39190da92fBrian Paul         break;
127737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      case OPCODE_OR:          /* bitwise OR */
127837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         {
127937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLuint a[4], b[4], result[4];
128037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            fetch_vector4ui(&inst->SrcReg[0], machine, a);
128137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            fetch_vector4ui(&inst->SrcReg[1], machine, b);
128237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[0] = a[0] | b[0];
128337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[1] = a[1] | b[1];
128437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[2] = a[2] | b[2];
128537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[3] = a[3] | b[3];
128637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            store_vector4ui(inst, machine, result);
128737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         }
128837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         break;
1289e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_PK2H:        /* pack two 16-bit floats in one 32-bit float */
1290e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
129137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLfloat a[4];
129237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLuint result[4];
1293e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLhalfNV hx, hy;
129433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
1295e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            hx = _mesa_float_to_half(a[0]);
1296e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            hy = _mesa_float_to_half(a[1]);
129737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[0] =
129837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[1] =
129937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[2] =
130037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[3] = hx | (hy << 16);
130137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            store_vector4ui(inst, machine, result);
1302e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1303e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1304e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_PK2US:       /* pack two GLushorts into one 32-bit float */
1305e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
130637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLfloat a[4];
130737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLuint result[4], usx, usy;
130833eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
1309e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[0] = CLAMP(a[0], 0.0F, 1.0F);
1310e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[1] = CLAMP(a[1], 0.0F, 1.0F);
1311c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            usx = F_TO_I(a[0] * 65535.0F);
1312c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            usy = F_TO_I(a[1] * 65535.0F);
131337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[0] =
131437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[1] =
131537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[2] =
131637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[3] = usx | (usy << 16);
131737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            store_vector4ui(inst, machine, result);
1318e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1319e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1320e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_PK4B:        /* pack four GLbytes into one 32-bit float */
1321e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
132237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLfloat a[4];
132337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLuint result[4], ubx, uby, ubz, ubw;
132433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
1325e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[0] = CLAMP(a[0], -128.0F / 127.0F, 1.0F);
1326e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[1] = CLAMP(a[1], -128.0F / 127.0F, 1.0F);
1327e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[2] = CLAMP(a[2], -128.0F / 127.0F, 1.0F);
1328e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[3] = CLAMP(a[3], -128.0F / 127.0F, 1.0F);
1329c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            ubx = F_TO_I(127.0F * a[0] + 128.0F);
1330c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            uby = F_TO_I(127.0F * a[1] + 128.0F);
1331c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            ubz = F_TO_I(127.0F * a[2] + 128.0F);
1332c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            ubw = F_TO_I(127.0F * a[3] + 128.0F);
133337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[0] =
133437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[1] =
133537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[2] =
133637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[3] = ubx | (uby << 8) | (ubz << 16) | (ubw << 24);
133737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            store_vector4ui(inst, machine, result);
1338e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1339e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1340e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_PK4UB:       /* pack four GLubytes into one 32-bit float */
1341e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
134237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLfloat a[4];
134337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLuint result[4], ubx, uby, ubz, ubw;
134433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
1345e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[0] = CLAMP(a[0], 0.0F, 1.0F);
1346e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[1] = CLAMP(a[1], 0.0F, 1.0F);
1347e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[2] = CLAMP(a[2], 0.0F, 1.0F);
1348e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[3] = CLAMP(a[3], 0.0F, 1.0F);
1349c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            ubx = F_TO_I(255.0F * a[0]);
1350c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            uby = F_TO_I(255.0F * a[1]);
1351c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            ubz = F_TO_I(255.0F * a[2]);
1352c9cb9cf0502f4ca179ed1b4dd763c94912843d38Brian Paul            ubw = F_TO_I(255.0F * a[3]);
135337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[0] =
135437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[1] =
135537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[2] =
135637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[3] = ubx | (uby << 8) | (ubz << 16) | (ubw << 24);
135737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            store_vector4ui(inst, machine, result);
1358e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1359e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1360e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_POW:
1361e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1362e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
136333eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, a);
136433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[1], machine, b);
1365e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = result[1] = result[2] = result[3]
1366fef303bc94f2fb15a068563ac8abfb1765bde035Eric Anholt               = (GLfloat) pow(a[0], b[0]);
1367e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1368e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1369e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1370b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul      case OPCODE_RCC:  /* clamped riciprocal */
1371b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul         {
1372b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            const float largest = 1.884467e+19, smallest = 5.42101e-20;
1373b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            GLfloat a[4], r, result[4];
1374b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            fetch_vector1(&inst->SrcReg[0], machine, a);
1375b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            if (DEBUG_PROG) {
1376b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               if (a[0] == 0)
1377b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul                  printf("RCC(0)\n");
1378b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               else if (IS_INF_OR_NAN(a[0]))
1379b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul                  printf("RCC(inf)\n");
1380b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            }
1381b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            if (a[0] == 1.0F) {
1382b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               r = 1.0F;
1383b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            }
1384b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            else {
1385b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               r = 1.0F / a[0];
1386b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            }
1387b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            if (positive(r)) {
1388b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               if (r > largest) {
1389b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul                  r = largest;
1390b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               }
1391b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               else if (r < smallest) {
1392b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul                  r = smallest;
1393b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               }
1394b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            }
1395b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            else {
1396b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               if (r < -largest) {
1397b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul                  r = -largest;
1398b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               }
1399b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               else if (r > -smallest) {
1400b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul                  r = -smallest;
1401b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul               }
1402b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            }
1403b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            result[0] = result[1] = result[2] = result[3] = r;
1404b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul            store_vector4(inst, machine, result);
1405b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul         }
1406b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul         break;
1407b4ad7c28430e4084d843cd99cf68209e95363963Brian Paul
1408e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_RCP:
1409e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1410e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
141133eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, a);
1412e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1413e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               if (a[0] == 0)
1414e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                  printf("RCP(0)\n");
1415e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               else if (IS_INF_OR_NAN(a[0]))
1416e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                  printf("RCP(inf)\n");
1417e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            }
1418e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = result[1] = result[2] = result[3] = 1.0F / a[0];
1419e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1420e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1421e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1422e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_RET:         /* return from subroutine (conditional) */
1423e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         if (eval_condition(machine, inst)) {
1424e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (machine->StackDepth == 0) {
1425e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               return GL_TRUE;  /* Per GL_NV_vertex_program2 spec */
142613e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1427a0275b0d2c071ed8254c2af3a0c53eec9d3561a6Brian            /* subtract one because of pc++ in the for loop */
1428a0275b0d2c071ed8254c2af3a0c53eec9d3561a6Brian            pc = machine->CallStack[--machine->StackDepth] - 1;
1429e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1430e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1431e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_RFL:         /* reflection vector */
1432e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1433e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat axis[4], dir[4], result[4], tmpX, tmpW;
143433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, axis);
143533eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, dir);
1436e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            tmpW = DOT3(axis, axis);
1437e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            tmpX = (2.0F * DOT3(axis, dir)) / tmpW;
1438e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = tmpX * axis[0] - dir[0];
1439e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = tmpX * axis[1] - dir[1];
1440e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = tmpX * axis[2] - dir[2];
1441e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            /* result[3] is never written! XXX enforce in parser! */
1442e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1443e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1444e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1445e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_RSQ:         /* 1 / sqrt() */
1446e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1447e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
144833eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, a);
1449e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            a[0] = FABSF(a[0]);
1450e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = result[1] = result[2] = result[3] = INV_SQRTF(a[0]);
1451e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1452e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1453e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("RSQ %g = 1/sqrt(|%g|)\n", result[0], a[0]);
145413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1455e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1456e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1457e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SCS:         /* sine and cos */
1458e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1459e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
146033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, a);
1461165694ad65374ff4330bd80acb398fe0428ba2e6Eric Anholt            result[0] = (GLfloat) cos(a[0]);
1462165694ad65374ff4330bd80acb398fe0428ba2e6Eric Anholt            result[1] = (GLfloat) sin(a[0]);
1463e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = 0.0;    /* undefined! */
1464e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = 0.0;    /* undefined! */
1465e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1466e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1467e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1468e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SEQ:         /* set on equal */
1469e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1470e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
147133eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
147233eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1473e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = (a[0] == b[0]) ? 1.0F : 0.0F;
1474e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = (a[1] == b[1]) ? 1.0F : 0.0F;
1475e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = (a[2] == b[2]) ? 1.0F : 0.0F;
1476e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = (a[3] == b[3]) ? 1.0F : 0.0F;
1477e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
147828ab1125c22bcb558e3b5e127d975120de76e103Brian            if (DEBUG_PROG) {
147928ab1125c22bcb558e3b5e127d975120de76e103Brian               printf("SEQ (%g %g %g %g) = (%g %g %g %g) == (%g %g %g %g)\n",
148028ab1125c22bcb558e3b5e127d975120de76e103Brian                      result[0], result[1], result[2], result[3],
148128ab1125c22bcb558e3b5e127d975120de76e103Brian                      a[0], a[1], a[2], a[3],
148228ab1125c22bcb558e3b5e127d975120de76e103Brian                      b[0], b[1], b[2], b[3]);
148328ab1125c22bcb558e3b5e127d975120de76e103Brian            }
1484e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1485e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1486e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SFL:         /* set false, operands ignored */
1487e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1488e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            static const GLfloat result[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
1489e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1490e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1491e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1492e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SGE:         /* set on greater or equal */
1493e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1494e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
149533eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
149633eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1497e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = (a[0] >= b[0]) ? 1.0F : 0.0F;
1498e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = (a[1] >= b[1]) ? 1.0F : 0.0F;
1499e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = (a[2] >= b[2]) ? 1.0F : 0.0F;
1500e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = (a[3] >= b[3]) ? 1.0F : 0.0F;
1501e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
150228ab1125c22bcb558e3b5e127d975120de76e103Brian            if (DEBUG_PROG) {
150328ab1125c22bcb558e3b5e127d975120de76e103Brian               printf("SGE (%g %g %g %g) = (%g %g %g %g) >= (%g %g %g %g)\n",
150428ab1125c22bcb558e3b5e127d975120de76e103Brian                      result[0], result[1], result[2], result[3],
150528ab1125c22bcb558e3b5e127d975120de76e103Brian                      a[0], a[1], a[2], a[3],
150628ab1125c22bcb558e3b5e127d975120de76e103Brian                      b[0], b[1], b[2], b[3]);
150728ab1125c22bcb558e3b5e127d975120de76e103Brian            }
1508e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1509e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1510e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SGT:         /* set on greater */
1511e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1512e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
151333eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
151433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1515e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = (a[0] > b[0]) ? 1.0F : 0.0F;
1516e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = (a[1] > b[1]) ? 1.0F : 0.0F;
1517e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = (a[2] > b[2]) ? 1.0F : 0.0F;
1518e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = (a[3] > b[3]) ? 1.0F : 0.0F;
1519e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1520e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
152128ab1125c22bcb558e3b5e127d975120de76e103Brian               printf("SGT (%g %g %g %g) = (%g %g %g %g) > (%g %g %g %g)\n",
152228ab1125c22bcb558e3b5e127d975120de76e103Brian                      result[0], result[1], result[2], result[3],
152328ab1125c22bcb558e3b5e127d975120de76e103Brian                      a[0], a[1], a[2], a[3],
152428ab1125c22bcb558e3b5e127d975120de76e103Brian                      b[0], b[1], b[2], b[3]);
152513e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1526e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1527e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1528e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SIN:
1529e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1530e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], result[4];
153133eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector1(&inst->SrcReg[0], machine, a);
1532e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = result[1] = result[2] = result[3]
1533165694ad65374ff4330bd80acb398fe0428ba2e6Eric Anholt               = (GLfloat) sin(a[0]);
1534e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1535e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1536e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1537e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SLE:         /* set on less or equal */
1538e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1539e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
154033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
154133eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1542e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = (a[0] <= b[0]) ? 1.0F : 0.0F;
1543e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = (a[1] <= b[1]) ? 1.0F : 0.0F;
1544e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = (a[2] <= b[2]) ? 1.0F : 0.0F;
1545e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = (a[3] <= b[3]) ? 1.0F : 0.0F;
1546e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
154728ab1125c22bcb558e3b5e127d975120de76e103Brian            if (DEBUG_PROG) {
154828ab1125c22bcb558e3b5e127d975120de76e103Brian               printf("SLE (%g %g %g %g) = (%g %g %g %g) <= (%g %g %g %g)\n",
154928ab1125c22bcb558e3b5e127d975120de76e103Brian                      result[0], result[1], result[2], result[3],
155028ab1125c22bcb558e3b5e127d975120de76e103Brian                      a[0], a[1], a[2], a[3],
155128ab1125c22bcb558e3b5e127d975120de76e103Brian                      b[0], b[1], b[2], b[3]);
155228ab1125c22bcb558e3b5e127d975120de76e103Brian            }
1553e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1554e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1555e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SLT:         /* set on less */
1556e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1557e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
155833eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
155933eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1560e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = (a[0] < b[0]) ? 1.0F : 0.0F;
1561e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = (a[1] < b[1]) ? 1.0F : 0.0F;
1562e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = (a[2] < b[2]) ? 1.0F : 0.0F;
1563e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = (a[3] < b[3]) ? 1.0F : 0.0F;
1564e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
156528ab1125c22bcb558e3b5e127d975120de76e103Brian            if (DEBUG_PROG) {
156628ab1125c22bcb558e3b5e127d975120de76e103Brian               printf("SLT (%g %g %g %g) = (%g %g %g %g) < (%g %g %g %g)\n",
156728ab1125c22bcb558e3b5e127d975120de76e103Brian                      result[0], result[1], result[2], result[3],
156828ab1125c22bcb558e3b5e127d975120de76e103Brian                      a[0], a[1], a[2], a[3],
156928ab1125c22bcb558e3b5e127d975120de76e103Brian                      b[0], b[1], b[2], b[3]);
157028ab1125c22bcb558e3b5e127d975120de76e103Brian            }
1571e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1572e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1573e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SNE:         /* set on not equal */
1574e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1575e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
157633eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
157733eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1578e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = (a[0] != b[0]) ? 1.0F : 0.0F;
1579e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = (a[1] != b[1]) ? 1.0F : 0.0F;
1580e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = (a[2] != b[2]) ? 1.0F : 0.0F;
1581e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = (a[3] != b[3]) ? 1.0F : 0.0F;
1582e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
158328ab1125c22bcb558e3b5e127d975120de76e103Brian            if (DEBUG_PROG) {
158428ab1125c22bcb558e3b5e127d975120de76e103Brian               printf("SNE (%g %g %g %g) = (%g %g %g %g) != (%g %g %g %g)\n",
158528ab1125c22bcb558e3b5e127d975120de76e103Brian                      result[0], result[1], result[2], result[3],
158628ab1125c22bcb558e3b5e127d975120de76e103Brian                      a[0], a[1], a[2], a[3],
158728ab1125c22bcb558e3b5e127d975120de76e103Brian                      b[0], b[1], b[2], b[3]);
158828ab1125c22bcb558e3b5e127d975120de76e103Brian            }
1589e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1590e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1591f6ead50827c03017e6b730313c361b39190da92fBrian Paul      case OPCODE_SSG:         /* set sign (-1, 0 or +1) */
1592f6ead50827c03017e6b730313c361b39190da92fBrian Paul         {
1593f6ead50827c03017e6b730313c361b39190da92fBrian Paul            GLfloat a[4], result[4];
1594f6ead50827c03017e6b730313c361b39190da92fBrian Paul            fetch_vector4(&inst->SrcReg[0], machine, a);
1595f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[0] = (GLfloat) ((a[0] > 0.0F) - (a[0] < 0.0F));
1596f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[1] = (GLfloat) ((a[1] > 0.0F) - (a[1] < 0.0F));
1597f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[2] = (GLfloat) ((a[2] > 0.0F) - (a[2] < 0.0F));
1598f6ead50827c03017e6b730313c361b39190da92fBrian Paul            result[3] = (GLfloat) ((a[3] > 0.0F) - (a[3] < 0.0F));
1599f6ead50827c03017e6b730313c361b39190da92fBrian Paul            store_vector4(inst, machine, result);
1600f6ead50827c03017e6b730313c361b39190da92fBrian Paul         }
1601f6ead50827c03017e6b730313c361b39190da92fBrian Paul         break;
1602e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_STR:         /* set true, operands ignored */
1603e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1604e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            static const GLfloat result[4] = { 1.0F, 1.0F, 1.0F, 1.0F };
1605e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1606e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1607e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1608e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SUB:
1609e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1610e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
161133eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
161233eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1613e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = a[0] - b[0];
1614e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[1] - b[1];
1615e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[2] - b[2];
1616e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = a[3] - b[3];
1617e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1618e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1619e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               printf("SUB (%g %g %g %g) = (%g %g %g %g) - (%g %g %g %g)\n",
1620e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      result[0], result[1], result[2], result[3],
1621e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
162213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1623e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1624e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1625e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_SWZ:         /* extended swizzle */
1626e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1627e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            const struct prog_src_register *source = &inst->SrcReg[0];
1628f4361540f8dd3016571523863b33481cba7a0c07Brian Paul            const GLfloat *src = get_src_register_pointer(source, machine);
1629e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat result[4];
1630e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLuint i;
1631e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            for (i = 0; i < 4; i++) {
1632e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               const GLuint swz = GET_SWZ(source->Swizzle, i);
1633e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               if (swz == SWIZZLE_ZERO)
1634e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                  result[i] = 0.0;
1635e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               else if (swz == SWIZZLE_ONE)
1636e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                  result[i] = 1.0;
1637e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               else {
1638e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                  ASSERT(swz >= 0);
1639e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                  ASSERT(swz <= 3);
1640e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                  result[i] = src[swz];
164113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian               }
16427db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul               if (source->Negate & (1 << i))
1643e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                  result[i] = -result[i];
164413e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian            }
1645e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1646e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1647e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1648e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_TEX:         /* Both ARB and NV frag prog */
1649999b55663a09d9669a9d14c5aadfa84e6dcba288Brian         /* Simple texel lookup */
1650e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1651999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            GLfloat texcoord[4], color[4];
1652999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            fetch_vector4(&inst->SrcReg[0], machine, texcoord);
1653999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
16540eb18ee55719377ebd90456bde605384ce4ec14aBrian Paul            /* For TEX, texcoord.Q should not be used and its value should not
16550eb18ee55719377ebd90456bde605384ce4ec14aBrian Paul             * matter (at most, we pass coord.xyz to texture3D() in GLSL).
16560eb18ee55719377ebd90456bde605384ce4ec14aBrian Paul             * Set Q=1 so that FetchTexelDeriv() doesn't get a garbage value
16570eb18ee55719377ebd90456bde605384ce4ec14aBrian Paul             * which is effectively what happens when the texcoord swizzle
16580eb18ee55719377ebd90456bde605384ce4ec14aBrian Paul             * is .xyzz
16590eb18ee55719377ebd90456bde605384ce4ec14aBrian Paul             */
16600eb18ee55719377ebd90456bde605384ce4ec14aBrian Paul            texcoord[3] = 1.0f;
16610eb18ee55719377ebd90456bde605384ce4ec14aBrian Paul
1662999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            fetch_texel(ctx, machine, inst, texcoord, 0.0, color);
1663999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
1664e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (DEBUG_PROG) {
1665999b55663a09d9669a9d14c5aadfa84e6dcba288Brian               printf("TEX (%g, %g, %g, %g) = texture[%d][%g, %g, %g, %g]\n",
1666e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      color[0], color[1], color[2], color[3],
1667e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                      inst->TexSrcUnit,
1668999b55663a09d9669a9d14c5aadfa84e6dcba288Brian                      texcoord[0], texcoord[1], texcoord[2], texcoord[3]);
1669e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            }
1670e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, color);
1671e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1672e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1673e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_TXB:         /* GL_ARB_fragment_program only */
1674e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         /* Texel lookup with LOD bias */
1675e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1676999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            GLfloat texcoord[4], color[4], lodBias;
1677999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
1678999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            fetch_vector4(&inst->SrcReg[0], machine, texcoord);
1679999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
1680999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            /* texcoord[3] is the bias to add to lambda */
1681890f37d4d96471a5c3d8ae286dfc13ad18ff78e5Brian Paul            lodBias = texcoord[3];
1682999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
1683999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            fetch_texel(ctx, machine, inst, texcoord, lodBias, color);
1684999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
1685be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul            if (DEBUG_PROG) {
1686be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul               printf("TXB (%g, %g, %g, %g) = texture[%d][%g %g %g %g]"
1687be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul                      "  bias %g\n",
1688be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul                      color[0], color[1], color[2], color[3],
1689be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul                      inst->TexSrcUnit,
1690be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul                      texcoord[0],
1691be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul                      texcoord[1],
1692be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul                      texcoord[2],
1693be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul                      texcoord[3],
1694be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul                      lodBias);
1695be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul            }
1696be2aa81f5f8f44be8c9c8854098d29635352c4f8Brian Paul
1697e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, color);
1698e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1699e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1700e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_TXD:         /* GL_NV_fragment_program only */
1701e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         /* Texture lookup w/ partial derivatives for LOD */
1702e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1703e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat texcoord[4], dtdx[4], dtdy[4], color[4];
170433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, texcoord);
170533eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, dtdx);
170633eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[2], machine, dtdy);
1707e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            machine->FetchTexelDeriv(ctx, texcoord, dtdx, dtdy,
1708999b55663a09d9669a9d14c5aadfa84e6dcba288Brian                                     0.0, /* lodBias */
1709e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                                     inst->TexSrcUnit, color);
1710e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, color);
1711e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1712e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
17130eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick      case OPCODE_TXL:
17140eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick         /* Texel lookup with explicit LOD */
17150eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick         {
17160eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick            GLfloat texcoord[4], color[4], lod;
17170eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick
17180eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick            fetch_vector4(&inst->SrcReg[0], machine, texcoord);
17190eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick
17200eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick            /* texcoord[3] is the LOD */
17210eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick            lod = texcoord[3];
17220eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick
17230eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick	    machine->FetchTexelLod(ctx, texcoord, lod,
17240eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick				   machine->Samplers[inst->TexSrcUnit], color);
17250eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick
17260eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick            store_vector4(inst, machine, color);
17270eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick         }
17280eb2026c8767d6e1f68e6b07f35a9aca9ed757c7Ian Romanick         break;
1729e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_TXP:         /* GL_ARB_fragment_program only */
1730e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         /* Texture lookup w/ projective divide */
1731e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1732999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            GLfloat texcoord[4], color[4];
1733999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
173433eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, texcoord);
1735e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            /* Not so sure about this test - if texcoord[3] is
1736e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian             * zero, we'd probably be fine except for an ASSERT in
1737e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian             * IROUND_POS() which gets triggered by the inf values created.
1738e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian             */
1739e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (texcoord[3] != 0.0) {
1740e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               texcoord[0] /= texcoord[3];
1741e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               texcoord[1] /= texcoord[3];
1742e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               texcoord[2] /= texcoord[3];
1743e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            }
1744999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
1745999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            fetch_texel(ctx, machine, inst, texcoord, 0.0, color);
1746999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
1747e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, color);
1748e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1749e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1750e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_TXP_NV:      /* GL_NV_fragment_program only */
1751999b55663a09d9669a9d14c5aadfa84e6dcba288Brian         /* Texture lookup w/ projective divide, as above, but do not
1752999b55663a09d9669a9d14c5aadfa84e6dcba288Brian          * do the divide by w if sampling from a cube map.
1753999b55663a09d9669a9d14c5aadfa84e6dcba288Brian          */
1754e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1755999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            GLfloat texcoord[4], color[4];
1756999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
175733eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, texcoord);
1758e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            if (inst->TexSrcTarget != TEXTURE_CUBE_INDEX &&
1759e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                texcoord[3] != 0.0) {
1760e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               texcoord[0] /= texcoord[3];
1761e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               texcoord[1] /= texcoord[3];
1762e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian               texcoord[2] /= texcoord[3];
1763e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            }
1764999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
1765999b55663a09d9669a9d14c5aadfa84e6dcba288Brian            fetch_texel(ctx, machine, inst, texcoord, 0.0, color);
1766999b55663a09d9669a9d14c5aadfa84e6dcba288Brian
1767e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, color);
1768e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1769e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1770035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul      case OPCODE_TRUNC:       /* truncate toward zero */
1771035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul         {
1772035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul            GLfloat a[4], result[4];
1773035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul            fetch_vector4(&inst->SrcReg[0], machine, a);
1774035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul            result[0] = (GLfloat) (GLint) a[0];
1775035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul            result[1] = (GLfloat) (GLint) a[1];
1776035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul            result[2] = (GLfloat) (GLint) a[2];
1777035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul            result[3] = (GLfloat) (GLint) a[3];
1778035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul            store_vector4(inst, machine, result);
1779035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul         }
1780035c0cf71a5fe3beee55654e1f7148adfe626cc0Brian Paul         break;
1781e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_UP2H:        /* unpack two 16-bit floats */
1782e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
17838d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            const GLuint raw = fetch_vector1ui(&inst->SrcReg[0], machine);
17848d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            GLfloat result[4];
17857b5ad23c7f7f9016f725cb1caa3cf8971aeedbc8Brian Paul            GLushort hx, hy;
17868d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            hx = raw & 0xffff;
17878d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            hy = raw >> 16;
1788e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = result[2] = _mesa_half_to_float(hx);
1789e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = result[3] = _mesa_half_to_float(hy);
1790e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1791e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1792e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1793e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_UP2US:       /* unpack two GLushorts */
1794e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
17958d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            const GLuint raw = fetch_vector1ui(&inst->SrcReg[0], machine);
17968d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            GLfloat result[4];
1797e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLushort usx, usy;
17988d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            usx = raw & 0xffff;
17998d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            usy = raw >> 16;
1800e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = result[2] = usx * (1.0f / 65535.0f);
1801e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = result[3] = usy * (1.0f / 65535.0f);
1802e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1803e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1804e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1805e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_UP4B:        /* unpack four GLbytes */
1806e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
18078d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            const GLuint raw = fetch_vector1ui(&inst->SrcReg[0], machine);
18088d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            GLfloat result[4];
18098d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            result[0] = (((raw >> 0) & 0xff) - 128) / 127.0F;
18108d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            result[1] = (((raw >> 8) & 0xff) - 128) / 127.0F;
18118d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            result[2] = (((raw >> 16) & 0xff) - 128) / 127.0F;
18128d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            result[3] = (((raw >> 24) & 0xff) - 128) / 127.0F;
1813e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1814e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1815e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1816e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_UP4UB:       /* unpack four GLubytes */
1817e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
18188d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            const GLuint raw = fetch_vector1ui(&inst->SrcReg[0], machine);
18198d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            GLfloat result[4];
18208d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            result[0] = ((raw >> 0) & 0xff) / 255.0F;
18218d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            result[1] = ((raw >> 8) & 0xff) / 255.0F;
18228d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            result[2] = ((raw >> 16) & 0xff) / 255.0F;
18238d1a01d37039a76ecbb8fdb4c10ff8d11aa02dfbBrian Paul            result[3] = ((raw >> 24) & 0xff) / 255.0F;
1824e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1825e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1826e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
182737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul      case OPCODE_XOR:         /* bitwise XOR */
182837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         {
182937eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            GLuint a[4], b[4], result[4];
183037eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            fetch_vector4ui(&inst->SrcReg[0], machine, a);
183137eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            fetch_vector4ui(&inst->SrcReg[1], machine, b);
183237eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[0] = a[0] ^ b[0];
183337eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[1] = a[1] ^ b[1];
183437eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[2] = a[2] ^ b[2];
183537eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            result[3] = a[3] ^ b[3];
183637eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul            store_vector4ui(inst, machine, result);
183737eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         }
183837eef7b474c5d9a7c566f9edf35c797c5a98d065Brian Paul         break;
1839e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_XPD:         /* cross product */
1840e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1841e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], result[4];
184233eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
184333eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
1844e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = a[1] * b[2] - a[2] * b[1];
1845e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[2] * b[0] - a[0] * b[2];
1846e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[0] * b[1] - a[1] * b[0];
1847e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = 1.0;
1848e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
18499637c963f59192aaccf68e7690f5ffb1e17ba077Brian            if (DEBUG_PROG) {
18509637c963f59192aaccf68e7690f5ffb1e17ba077Brian               printf("XPD (%g %g %g %g) = (%g %g %g) X (%g %g %g)\n",
18519637c963f59192aaccf68e7690f5ffb1e17ba077Brian                      result[0], result[1], result[2], result[3],
18529637c963f59192aaccf68e7690f5ffb1e17ba077Brian                      a[0], a[1], a[2], b[0], b[1], b[2]);
18539637c963f59192aaccf68e7690f5ffb1e17ba077Brian            }
1854e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1855e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1856e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_X2D:         /* 2-D matrix transform */
1857e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
1858e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            GLfloat a[4], b[4], c[4], result[4];
185933eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[0], machine, a);
186033eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[1], machine, b);
186133eac56e4a48143aa8acd5757feb68570e860de5Brian            fetch_vector4(&inst->SrcReg[2], machine, c);
1862e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[0] = a[0] + b[0] * c[0] + b[1] * c[1];
1863e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[1] = a[1] + b[0] * c[2] + b[1] * c[3];
1864e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[2] = a[2] + b[0] * c[0] + b[1] * c[1];
1865e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            result[3] = a[3] + b[0] * c[2] + b[1] * c[3];
1866e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian            store_vector4(inst, machine, result);
1867e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1868e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1869e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_PRINT:
1870e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         {
18714e98116c234c25119c1a3a0c0a138ada2ab69906Vinson Lee            if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
187245df4bad9fc0379f05197bee10c03fd351f24094Vinson Lee               GLfloat a[4];
187345df4bad9fc0379f05197bee10c03fd351f24094Vinson Lee               fetch_vector4(&inst->SrcReg[0], machine, a);
187445df4bad9fc0379f05197bee10c03fd351f24094Vinson Lee               printf("%s%g, %g, %g, %g\n", (const char *) inst->Data,
187545df4bad9fc0379f05197bee10c03fd351f24094Vinson Lee                            a[0], a[1], a[2], a[3]);
187645df4bad9fc0379f05197bee10c03fd351f24094Vinson Lee            }
187745df4bad9fc0379f05197bee10c03fd351f24094Vinson Lee            else {
187845df4bad9fc0379f05197bee10c03fd351f24094Vinson Lee               printf("%s\n", (const char *) inst->Data);
187945df4bad9fc0379f05197bee10c03fd351f24094Vinson Lee            }
1880e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         }
1881e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         break;
1882e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      case OPCODE_END:
1883e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         return GL_TRUE;
1884e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian      default:
1885936dba1de5ca0d4252061c4a93674fad2d66d202Alan Hourihane         _mesa_problem(ctx, "Bad opcode %d in _mesa_execute_program",
1886e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian                       inst->Opcode);
1887e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian         return GL_TRUE;        /* return value doesn't matter */
188813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
1889e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian
1890cfd0011f2fe3aad2ea0f66c151b3fb12d05f644eBrian      numExec++;
1891cfd0011f2fe3aad2ea0f66c151b3fb12d05f644eBrian      if (numExec > maxExec) {
1892cc15ef07e03e465d93df7062a516f9b4bfbaeda0Eric Anholt	 static GLboolean reported = GL_FALSE;
1893cc15ef07e03e465d93df7062a516f9b4bfbaeda0Eric Anholt	 if (!reported) {
1894cc15ef07e03e465d93df7062a516f9b4bfbaeda0Eric Anholt	    _mesa_problem(ctx, "Infinite loop detected in fragment program");
1895cc15ef07e03e465d93df7062a516f9b4bfbaeda0Eric Anholt	    reported = GL_TRUE;
1896cc15ef07e03e465d93df7062a516f9b4bfbaeda0Eric Anholt	 }
189713e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian         return GL_TRUE;
189813e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian      }
1899e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian
1900e80d901d9854b7c24a71fcd5a3377c33f408c8c0Brian   } /* for pc */
190113e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian
190213e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian   return GL_TRUE;
190313e3b21b16b14112b416f3ee5742fc7bd1b2d823Brian}
1904