Symbol names are prepended with an underscore on CYGWIN as well.
[mesa.git] / src / mesa / tnl / t_vtx_x86.c
index 4713a325bf2d17945c043e1fc85d85445af09452..59a869879a516289ede3480c418fe69fa6d7ce39 100644 (file)
@@ -1,7 +1,6 @@
-/* $XFree86$ */
 /**************************************************************************
 
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+Copyright 2004 Tungsten Graphics Inc., Cedar Park, Texas.
 
 All Rights Reserved.
 
@@ -19,7 +18,7 @@ Software.
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -29,699 +28,357 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 /*
  * Authors:
  *   Keith Whitwell <keith@tungstengraphics.com>
+ *   Daniel Borca <dborca@yahoo.com>
  */
 
-#include <stdio.h>
-#include <assert.h>
-#include "mem.h" 
-#include "mmath.h" 
-#include "simple_list.h" 
-#include "tnl_vtxfmt.h"
 
-#if defined(USE_X86_ASM)
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "vtxfmt.h"
+#include "dlist.h"
+#include "state.h"
+#include "light.h"
+#include "api_arrayelt.h"
+#include "api_noop.h"
+#include "t_vtx_api.h"
+#include "simple_list.h"
+
+
+#if defined(USE_X86_ASM) && !defined(HAVE_NONSTANDARD_GLAPIENTRY)
+
+#define EXTERN( FUNC )         \
+extern const char *FUNC;       \
+extern const char *FUNC##_end
+
+EXTERN( _tnl_x86_Attribute1fv );
+EXTERN( _tnl_x86_Attribute2fv );
+EXTERN( _tnl_x86_Attribute3fv );
+EXTERN( _tnl_x86_Attribute4fv );
+EXTERN( _tnl_x86_Vertex1fv );
+EXTERN( _tnl_x86_Vertex2fv );
+EXTERN( _tnl_x86_Vertex3fv );
+EXTERN( _tnl_x86_Vertex4fv );
+
+EXTERN( _tnl_x86_dispatch_attrf1 );
+EXTERN( _tnl_x86_dispatch_attrf2 );
+EXTERN( _tnl_x86_dispatch_attrf3 );
+EXTERN( _tnl_x86_dispatch_attrf4 );
+EXTERN( _tnl_x86_dispatch_attrfv );
+EXTERN( _tnl_x86_dispatch_multitexcoordf1 );
+EXTERN( _tnl_x86_dispatch_multitexcoordf2 );
+EXTERN( _tnl_x86_dispatch_multitexcoordf3 );
+EXTERN( _tnl_x86_dispatch_multitexcoordf4 );
+EXTERN( _tnl_x86_dispatch_multitexcoordfv );
+EXTERN( _tnl_x86_dispatch_vertexattribf1 );
+EXTERN( _tnl_x86_dispatch_vertexattribf2 );
+EXTERN( _tnl_x86_dispatch_vertexattribf3 );
+EXTERN( _tnl_x86_dispatch_vertexattribf4 );
+EXTERN( _tnl_x86_dispatch_vertexattribfv );
+
+EXTERN( _tnl_x86_choose_fv );
+
+
+#define DONT_KNOW_OFFSETS 1
+
+
+#define DFN( FUNC, CACHE, KEY )                                \
+   struct _tnl_dynfn *dfn = MALLOC_STRUCT( _tnl_dynfn );\
+   char *start = (char *)&FUNC;                                \
+   char *end = (char *)&FUNC##_end;                    \
+   int offset = 0;                                     \
+   insert_at_head( &CACHE, dfn );                      \
+   dfn->key = KEY;                                     \
+   dfn->code = ALIGN_MALLOC( end - start, 16 );                \
+   memcpy (dfn->code, start, end - start)
+
+
+
+#define FIXUP( CODE, KNOWN_OFFSET, CHECKVAL, NEWVAL )  \
+do {                                                   \
+   GLint subst = 0x10101010 + CHECKVAL;                        \
+                                                       \
+   if (DONT_KNOW_OFFSETS) {                            \
+      while (*(int *)(CODE+offset) != subst) offset++; \
+      *(int *)(CODE+offset) = (int)(NEWVAL);           \
+      if (0) fprintf(stderr, "%s/%d: offset %d, new value: 0x%x\n", __FILE__, __LINE__, offset, (int)(NEWVAL)); \
+      offset += 4;                                     \
+   }                                                   \
+   else {                                              \
+      int *icode = (int *)(CODE+KNOWN_OFFSET);         \
+      assert (*icode == subst);                                \
+      *icode = (int)NEWVAL;                            \
+   }                                                   \
+} while (0)
+
+
+
+#define FIXUPREL( CODE, KNOWN_OFFSET, CHECKVAL, NEWVAL )\
+do {                                                   \
+   GLint subst = 0x10101010 + CHECKVAL;                        \
+                                                       \
+   if (DONT_KNOW_OFFSETS) {                            \
+      while (*(int *)(CODE+offset) != subst) offset++; \
+      *(int *)(CODE+offset) = (int)(NEWVAL) - ((int)(CODE)+offset) - 4; \
+      if (0) fprintf(stderr, "%s/%d: offset %d, new value: 0x%x\n", __FILE__, __LINE__, offset, (int)(NEWVAL) - ((int)(CODE)+offset) - 4); \
+      offset += 4;                                     \
+   }                                                   \
+   else {                                              \
+      int *icode = (int *)(CODE+KNOWN_OFFSET);         \
+      assert (*icode == subst);                                \
+      *icode = (int)(NEWVAL) - (int)(icode) - 4;       \
+   }                                                   \
+} while (0)
+
+
+
 
 /* Build specialized versions of the immediate calls on the fly for
  * the current state.  Generic x86 versions.
  */
 
-struct dynfn *tnl_makeX86Vertex3f( TNLcontext *tnl, int key )
+static struct _tnl_dynfn *makeX86Vertex1fv( GLcontext *ctx, int vertex_size )
 {
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (RADEON_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   switch (tnl->vertex_size) {
-   case 4: {
-      static  char temp[] = {
-        0x8b, 0x0d, 0,0,0,0,           /* mov    DMAPTR,%ecx */
-        0x8b, 0x44, 0x24, 0x04,        /* mov    0x4(%esp,1),%eax */
-        0x8b, 0x54, 0x24, 0x08,        /* mov    0x8(%esp,1),%edx */
-        0x89, 0x01,                    /* mov    %eax,(%ecx) */
-        0x89, 0x51, 0x04,              /* mov    %edx,0x4(%ecx) */
-        0x8b, 0x44, 0x24, 0x0c,        /* mov    0xc(%esp,1),%eax */
-        0x8b, 0x15, 0,0,0,0,           /* mov    VERTEX[3],%edx */
-        0x89, 0x41, 0x08,              /* mov    %eax,0x8(%ecx) */
-        0x89, 0x51, 0x0c,              /* mov    %edx,0xc(%ecx) */
-        0xa1, 0, 0, 0, 0,              /* mov    COUNTER,%eax */
-        0x83, 0xc1, 0x10,              /* add    $0x10,%ecx */
-        0x48,                          /* dec    %eax */
-        0x89, 0x0d, 0,0,0,0,           /* mov    %ecx,DMAPTR */
-        0xa3, 0, 0, 0, 0,              /* mov    %eax,COUNTER */
-        0x74, 0x01,                    /* je     +1 */
-        0xc3,                          /* ret     */
-        0xff, 0x25, 0,0,0,0            /* jmp    *NOTIFY */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 2, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 25, 0x0, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 36, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 46, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 51, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 60, 0x0, (int)&tnl->notify);
-      break;
-   }
-   case 6: {
-      static  char temp[] = {
-        0x57,                          /* push   %edi */
-        0x8b, 0x3d, 0, 0, 0, 0,        /* mov    DMAPTR,%edi */
-        0x8b, 0x44, 0x24, 0x8,         /* mov    0x8(%esp,1),%eax */
-        0x8b, 0x54, 0x24, 0xc,         /* mov    0xc(%esp,1),%edx */
-        0x8b, 0x4c, 0x24, 0x10,        /* mov    0x10(%esp,1),%ecx */
-        0x89, 0x07,                    /* mov    %eax,(%edi) */
-        0x89, 0x57, 0x04,              /* mov    %edx,0x4(%edi) */
-        0x89, 0x4f, 0x08,              /* mov    %ecx,0x8(%edi) */
-        0xa1, 0, 0, 0, 0,              /* mov    VERTEX[3],%eax */
-        0x8b, 0x15, 0, 0, 0, 0,        /* mov    VERTEX[4],%edx */
-        0x8b, 0x0d, 0, 0, 0, 0,        /* mov    VERTEX[5],%ecx */
-        0x89, 0x47, 0x0c,              /* mov    %eax,0xc(%edi) */
-        0x89, 0x57, 0x10,              /* mov    %edx,0x10(%edi) */
-        0x89, 0x4f, 0x14,              /* mov    %ecx,0x14(%edi) */
-        0x83, 0xc7, 0x18,              /* add    $0x18,%edi */
-        0xa1, 0, 0, 0, 0,              /* mov    COUNTER,%eax */
-        0x89, 0x3d, 0, 0, 0, 0,        /* mov    %edi,DMAPTR */
-        0x48,                          /* dec    %eax */
-        0x5f,                          /* pop    %edi */
-        0xa3, 0, 0, 0, 0,              /* mov    %eax,COUNTER */
-        0x74, 0x01,                    /* je     +1 */
-        0xc3,                          /* ret     */
-        0xff, 0x25, 0,0,0,0,           /* jmp    *NOTIFY */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 3, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 28, 0x0, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 34, 0x0, (int)&tnl->vertex[4]);
-      FIXUP(dfn->code, 40, 0x0, (int)&tnl->vertex[5]);
-      FIXUP(dfn->code, 57, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 63, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 70, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 79, 0x0, (int)&tnl->notify);
-      break;
-   }
-   default: {
-      /* Repz convenient as it's possible to emit code for any size
-       * vertex with little tweaking.  Might as well read vertsize
-       * though, and have only one of these.
-       */
-      static  char temp[] = {
-        0x57,                          /* push   %edi */
-        0x56,                          /* push   %esi */
-        0xbe, 0, 0, 0, 0,              /* mov    $VERTEX+3,%esi */
-        0x8b, 0x3d, 0, 0, 0, 0,        /* mov    DMAPTR,%edi */
-        0x8b, 0x44, 0x24, 0x0c,        /* mov    0x0c(%esp,1),%eax */
-        0x8b, 0x54, 0x24, 0x10,        /* mov    0x10(%esp,1),%edx */
-        0x8b, 0x4c, 0x24, 0x14,        /* mov    0x14(%esp,1),%ecx */
-        0x89, 0x07,                    /* mov    %eax,(%edi) */
-        0x89, 0x57, 0x04,              /* mov    %edx,0x4(%edi) */
-        0x89, 0x4f, 0x08,              /* mov    %ecx,0x8(%edi) */
-        0x83, 0xc7, 0x0c,              /* add    $0xc,%edi */
-        0xb9, 0, 0, 0, 0,              /* mov    $VERTSIZE-3,%ecx */
-        0xf3, 0xa5,                    /* repz movsl %ds:(%esi),%es:(%edi)*/
-        0xa1, 0, 0, 0, 0,              /* mov    COUNTER,%eax */
-        0x89, 0x3d, 0, 0, 0, 0,        /* mov    %edi,DMAPTR */
-        0x48,                          /* dec    %eax */
-        0xa3, 0, 0, 0, 0,              /* mov    %eax,COUNTER */
-        0x5e,                          /* pop    %esi */
-        0x5f,                          /* pop    %edi */
-        0x74, 0x01,                    /* je     +1 */
-        0xc3,                          /* ret     */
-        0xff, 0x25, 0, 0, 0, 0         /* jmp    NOTIFY */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-3);
-      FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
-   break;
-   }
-   }
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _tnl_x86_Vertex1fv, tnl->vtx.cache.Vertex[1-1], vertex_size );
+
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 1, vertex_size - 1);
+   FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[1]);
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 4, (int)ctx);
+   FIXUPREL(dfn->code, 0, 5, (int)&_tnl_wrap_filled_vertex);
 
-   insert_at_head( &tnl->dfn_cache.Vertex3f, dfn );
-   dfn->key = key;
    return dfn;
 }
 
+static struct _tnl_dynfn *makeX86Vertex2fv( GLcontext *ctx, int vertex_size )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _tnl_x86_Vertex2fv, tnl->vtx.cache.Vertex[2-1], vertex_size );
+
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 1, vertex_size - 2);
+   FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[2]);
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 4, (int)ctx);
+   FIXUPREL(dfn->code, 0, 5, (int)&_tnl_wrap_filled_vertex);
 
+   return dfn;
+}
 
-struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *tnl, int key )
+static struct _tnl_dynfn *makeX86Vertex3fv( GLcontext *ctx, int vertex_size )
 {
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   switch (tnl->vertex_size) {
-   case 6: {
-      static  char temp[] = {
-        0xa1, 0x00, 0x00, 0, 0,        /* mov    0x0,%eax */
-        0x8b, 0x4c, 0x24, 0x04,        /* mov    0x4(%esp,1),%ecx */
-        0x8b, 0x11,                    /* mov    (%ecx),%edx */
-        0x89, 0x10,                    /* mov    %edx,(%eax) */
-        0x8b, 0x51, 0x04,              /* mov    0x4(%ecx),%edx */
-        0x8b, 0x49, 0x08,              /* mov    0x8(%ecx),%ecx */
-        0x89, 0x50, 0x04,              /* mov    %edx,0x4(%eax) */
-        0x89, 0x48, 0x08,              /* mov    %ecx,0x8(%eax) */
-        0x8b, 0x15, 0x1c, 0, 0, 0,     /* mov    0x1c,%edx */
-        0x8b, 0x0d, 0x20, 0, 0, 0,     /* mov    0x20,%ecx */
-        0x89, 0x50, 0x0c,              /* mov    %edx,0xc(%eax) */
-        0x89, 0x48, 0x10,              /* mov    %ecx,0x10(%eax) */
-        0x8b, 0x15, 0x24, 0, 0, 0,     /* mov    0x24,%edx */
-        0x89, 0x50, 0x14,              /* mov    %edx,0x14(%eax) */
-        0x83, 0xc0, 0x18,              /* add    $0x18,%eax */
-        0xa3, 0x00, 0x00, 0, 0,        /* mov    %eax,0x0 */
-        0xa1, 0x04, 0x00, 0, 0,        /* mov    0x4,%eax */
-        0x48,                          /* dec    %eax */
-        0xa3, 0x04, 0x00, 0, 0,        /* mov    %eax,0x4 */
-        0x74, 0x01,                    /* je     2a4 <.f11> */
-        0xc3,                          /* ret     */
-        0xff, 0x25, 0x08, 0, 0, 0,     /* jmp    *0x8 */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]);
-      FIXUP(dfn->code, 45, 0x00000024, (int)&tnl->vertex[5]);
-      FIXUP(dfn->code, 56, 0x00000000, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 61, 0x00000004, (int)&tnl->counter);
-      FIXUP(dfn->code, 67, 0x00000004, (int)&tnl->counter);
-      FIXUP(dfn->code, 76, 0x00000008, (int)&tnl->notify);
-      break;
-   }
-   
-
-   case 8: {
-      static  char temp[] = {
-        0xa1, 0x00, 0x00, 0, 0,        /* mov    0x0,%eax */
-        0x8b, 0x4c, 0x24, 0x04,        /* mov    0x4(%esp,1),%ecx */
-        0x8b, 0x11,                    /* mov    (%ecx),%edx */
-        0x89, 0x10,                    /* mov    %edx,(%eax) */
-        0x8b, 0x51, 0x04,              /* mov    0x4(%ecx),%edx */
-        0x8b, 0x49, 0x08,              /* mov    0x8(%ecx),%ecx */
-        0x89, 0x50, 0x04,              /* mov    %edx,0x4(%eax) */
-        0x89, 0x48, 0x08,              /* mov    %ecx,0x8(%eax) */
-        0x8b, 0x15, 0x1c, 0, 0, 0,     /* mov    0x1c,%edx */
-        0x8b, 0x0d, 0x20, 0, 0, 0,     /* mov    0x20,%ecx */
-        0x89, 0x50, 0x0c,              /* mov    %edx,0xc(%eax) */
-        0x89, 0x48, 0x10,              /* mov    %ecx,0x10(%eax) */
-        0x8b, 0x15, 0x1c, 0, 0, 0,     /* mov    0x1c,%edx */
-        0x8b, 0x0d, 0x20, 0, 0, 0,     /* mov    0x20,%ecx */
-        0x89, 0x50, 0x14,              /* mov    %edx,0x14(%eax) */
-        0x89, 0x48, 0x18,              /* mov    %ecx,0x18(%eax) */
-        0x8b, 0x15, 0x24, 0, 0, 0,     /* mov    0x24,%edx */
-        0x89, 0x50, 0x1c,              /* mov    %edx,0x1c(%eax) */
-        0x83, 0xc0, 0x20,              /* add    $0x20,%eax */
-        0xa3, 0x00, 0x00, 0, 0,        /* mov    %eax,0x0 */
-        0xa1, 0x04, 0x00, 0, 0,        /* mov    0x4,%eax */
-        0x48,                          /* dec    %eax */
-        0xa3, 0x04, 0x00, 0, 0,        /* mov    %eax,0x4 */
-        0x74, 0x01,                    /* je     2a4 <.f11> */
-        0xc3,                          /* ret     */
-        0xff, 0x25, 0x08, 0, 0, 0,     /* jmp    *0x8 */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]);
-      FIXUP(dfn->code, 45, 0x0000001c, (int)&tnl->vertex[5]);
-      FIXUP(dfn->code, 51, 0x00000020, (int)&tnl->vertex[6]);
-      FIXUP(dfn->code, 63, 0x00000024, (int)&tnl->vertex[7]);
-      FIXUP(dfn->code, 74, 0x00000000, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 79, 0x00000004, (int)&tnl->counter);
-      FIXUP(dfn->code, 85, 0x00000004, (int)&tnl->counter);
-      FIXUP(dfn->code, 94, 0x00000008, (int)&tnl->notify);
-      break;
-   }
-   
-
-
-   default: {
-      /* Repz convenient as it's possible to emit code for any size
-       * vertex with little tweaking.  Might as well read vertsize
-       * though, and have only one of these.
-       */
-      static  char temp[] = {
-        0x8b, 0x54, 0x24, 0x04,        /* mov    0x4(%esp,1),%edx */
-        0x57,                          /* push   %edi */
-        0x56,                          /* push   %esi */
-        0x8b, 0x3d, 1,1,1,1,           /* mov    DMAPTR,%edi */
-        0x8b, 0x02,                    /* mov    (%edx),%eax */
-        0x8b, 0x4a, 0x04,              /* mov    0x4(%edx),%ecx */
-        0x8b, 0x72, 0x08,              /* mov    0x8(%edx),%esi */
-        0x89, 0x07,                    /* mov    %eax,(%edi) */
-        0x89, 0x4f, 0x04,              /* mov    %ecx,0x4(%edi) */
-        0x89, 0x77, 0x08,              /* mov    %esi,0x8(%edi) */
-        0x83, 0xc7, 0x0c,              /* add    $0xc,%edi */
-        0xb9, 0x06, 0x00, 0x00, 0x00,  /* mov    $VERTSIZE-3,%ecx */
-        0xbe, 0x58, 0x00, 0x00, 0x00,  /* mov    $VERTEX[3],%esi */
-        0xf3, 0xa5,                    /* repz movsl %ds:(%esi),%es:(%edi)*/
-        0x89, 0x3d, 1, 1, 1, 1,        /* mov    %edi,DMAPTR */
-        0xa1, 2, 2, 2, 2,              /* mov    COUNTER,%eax */
-        0x5e,                          /* pop    %esi */
-        0x5f,                          /* pop    %edi */
-        0x48,                          /* dec    %eax */
-        0xa3, 2, 2, 2, 2,              /* mov    %eax,COUNTER */
-        0x74, 0x01,                    /* je     +1 */
-        0xc3,                          /* ret     */
-        0xff, 0x25, 0, 0, 0, 0         /* jmp    NOTIFY */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 8, 0x01010101, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 32, 0x00000006, tnl->vertex_size-3);
-      FIXUP(dfn->code, 37, 0x00000058, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 45, 0x01010101, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 50, 0x02020202, (int)&tnl->counter);
-      FIXUP(dfn->code, 58, 0x02020202, (int)&tnl->counter);
-      FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
-   break;
-   }
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _tnl_x86_Vertex3fv, tnl->vtx.cache.Vertex[3-1], vertex_size );
+
+   switch (vertex_size) {
+      default: {
+         FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+         FIXUP(dfn->code, 0, 1, vertex_size - 3);
+         FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[3]);
+         FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+         FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+         FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+         FIXUP(dfn->code, 0, 4, (int)ctx);
+         FIXUPREL(dfn->code, 0, 5, (int)&_tnl_wrap_filled_vertex);
+         return dfn;
+      }
    }
+}
+
+static struct _tnl_dynfn *makeX86Vertex4fv( GLcontext *ctx, int vertex_size )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _tnl_x86_Vertex4fv, tnl->vtx.cache.Vertex[4-1], vertex_size );
+
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 1, vertex_size - 4);
+   FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[4]);
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 4, (int)ctx);
+   FIXUPREL(dfn->code, 0, 5, (int)&_tnl_wrap_filled_vertex);
 
-   insert_at_head( &tnl->dfn_cache.Vertex3fv, dfn );
-   dfn->key = key;
    return dfn;
 }
 
 
-struct dynfn *tnl_makeX86Normal3fv( TNLcontext *tnl, int key )
+static struct _tnl_dynfn *makeX86Attribute1fv( GLcontext *ctx, int dest )
 {
-   static  char temp[] = {
-      0x8b, 0x44, 0x24, 0x04,                  /* mov    0x4(%esp,1),%eax */
-      0xba, 0, 0, 0, 0,                /* mov    $DEST,%edx */
-      0x8b, 0x08,                      /* mov    (%eax),%ecx */
-      0x89, 0x0a,                      /* mov    %ecx,(%edx) */
-      0x8b, 0x48, 0x04,                /* mov    0x4(%eax),%ecx */
-      0x89, 0x4a, 0x04,                /* mov    %ecx,0x4(%edx) */
-      0x8b, 0x48, 0x08,                /* mov    0x8(%eax),%ecx */
-      0x89, 0x4a, 0x08,                /* mov    %ecx,0x8(%edx) */
-      0xc3,                            /* ret    */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.Normal3fv, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr); 
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _tnl_x86_Attribute1fv, tnl->vtx.cache.Attribute[1-1], dest );
+
+   FIXUP(dfn->code, 0, 0, dest); 
+
    return dfn;
 }
 
-struct dynfn *tnl_makeX86Normal3f( TNLcontext *tnl, int key )
+static struct _tnl_dynfn *makeX86Attribute2fv( GLcontext *ctx, int dest )
 {
-   static  char temp[] = {
-      0xba, 0x78, 0x56, 0x34, 0x12,            /*  mov    $DEST,%edx */
-      0x8b, 0x44, 0x24, 0x04,                  /*  mov    0x4(%esp,1),%eax */
-      0x89, 0x02,                      /*  mov    %eax,(%edx) */
-      0x8b, 0x44, 0x24, 0x08,                  /*  mov    0x8(%esp,1),%eax */
-      0x89, 0x42, 0x04,                /*  mov    %eax,0x4(%edx) */
-      0x8b, 0x44, 0x24, 0x0c,                  /*  mov    0xc(%esp,1),%eax */
-      0x89, 0x42, 0x08,                /*  mov    %eax,0x8(%edx) */
-      0xc3,                            /*  ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.Normal3f, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr); 
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _tnl_x86_Attribute2fv, tnl->vtx.cache.Attribute[2-1], dest );
+
+   FIXUP(dfn->code, 0, 0, dest); 
+   FIXUP(dfn->code, 0, 1, 4+dest); 
+
    return dfn;
 }
 
-struct dynfn *tnl_makeX86Color4ubv( TNLcontext *tnl, int key )
+static struct _tnl_dynfn *makeX86Attribute3fv( GLcontext *ctx, int dest )
 {
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-   insert_at_head( &tnl->dfn_cache.Color4ubv, dfn );
-   dfn->key = key;
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   if (key & TNL_CP_VC_FRMT_PKCOLOR) {
-      static  char temp[] = {
-        0x8b, 0x44, 0x24, 0x04,        /*  mov    0x4(%esp,1),%eax */
-        0xba, 0x78, 0x56, 0x34, 0x12,  /*  mov    $DEST,%edx */
-        0x8b, 0x00,                    /*  mov    (%eax),%eax */
-        0x89, 0x02,                    /*  mov    %eax,(%edx) */
-        0xc3,                          /*  ret     */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 5, 0x12345678, (int)tnl->ubytecolorptr); 
-      return dfn;
-   } 
-   else {
-      static  char temp[] = {
-        0x53,                                  /* push   %ebx */
-        0xba, 0x00, 0x00, 0x00, 0x00,          /* mov    $0x0,%edx */
-        0x31, 0xc0,                            /* xor    %eax,%eax */
-        0x31, 0xc9,                            /* xor    %ecx,%ecx */
-        0x8b, 0x5c, 0x24, 0x08,                /* mov    0x8(%esp,1), %ebx */
-        0x8b, 0x1b,                            /* mov    (%ebx), %ebx */
-        0x88, 0xd8,                            /* mov    %bl, %al */
-        0x88, 0xf9,                            /* mov    %bh, %cl */
-        0x8b, 0x04, 0x82,                      /* mov    (%edx,%eax,4),%eax */
-        0x8b, 0x0c, 0x8a,                      /* mov    (%edx,%ecx,4),%ecx */
-        0xa3, 0xaf, 0xbe, 0xad, 0xde,          /* mov    %eax,0xdeadbeaf */
-        0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde,    /* mov    %ecx,0xdeadbeaf */
-        0x31, 0xc0,                            /* xor    %eax,%eax */
-        0x31, 0xc9,                            /* xor    %ecx,%ecx */
-        0xc1, 0xeb, 0x10,                      /* shr    $0x10, %ebx */
-        0x88, 0xd8,                            /* mov    %bl, %al */
-        0x88, 0xf9,                            /* mov    %bh, %cl */
-        0x8b, 0x04, 0x82,                      /* mov    (%edx,%eax,4),%eax */
-        0x8b, 0x0c, 0x8a,                      /* mov    (%edx,%ecx,4),%ecx */
-        0xa3, 0xaf, 0xbe, 0xad, 0xde,          /* mov    %eax,0xdeadbeaf */
-        0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde,    /* mov    %ecx,0xdeadbeaf */
-        0x5b,                                  /* pop    %ebx */
-        0xc3,                                  /* ret     */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab); 
-      FIXUP(dfn->code, 27, 0xdeadbeaf, (int)tnl->floatcolorptr); 
-      FIXUP(dfn->code, 33, 0xdeadbeaf, (int)tnl->floatcolorptr+4); 
-      FIXUP(dfn->code, 55, 0xdeadbeaf, (int)tnl->floatcolorptr+8); 
-      FIXUP(dfn->code, 61, 0xdeadbeaf, (int)tnl->floatcolorptr+12); 
-      return dfn;
-   }
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _tnl_x86_Attribute3fv, tnl->vtx.cache.Attribute[3-1], dest );
+
+   FIXUP(dfn->code, 0, 0, dest); 
+   FIXUP(dfn->code, 0, 1, 4+dest); 
+   FIXUP(dfn->code, 0, 2, 8+dest);
+
+   return dfn;
 }
 
-struct dynfn *tnl_makeX86Color4ub( TNLcontext *tnl, int key )
+static struct _tnl_dynfn *makeX86Attribute4fv( GLcontext *ctx, int dest )
 {
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   if (key & TNL_CP_VC_FRMT_PKCOLOR) {
-      /* XXX push/pop */
-      static  char temp[] = {
-        0x53,                          /* push   %ebx */
-        0x8b, 0x44, 0x24, 0x08,                /* mov    0x8(%esp,1),%eax */
-        0x8b, 0x54, 0x24, 0x0c,                /* mov    0xc(%esp,1),%edx */
-        0x8b, 0x4c, 0x24, 0x10,                /* mov    0x10(%esp,1),%ecx */
-        0x8b, 0x5c, 0x24, 0x14,                /* mov    0x14(%esp,1),%ebx */
-        0xa2, 0, 0, 0, 0,              /* mov    %al,DEST */
-        0x88, 0x15, 0, 0, 0, 0,        /* mov    %dl,DEST+1 */
-        0x88, 0x0d, 0, 0, 0, 0,        /* mov    %cl,DEST+2 */
-        0x88, 0x1d, 0, 0, 0, 0,        /* mov    %bl,DEST+3 */
-        0x5b,                          /* pop    %ebx */
-        0xc3,                          /* ret     */
-      };
-
-      struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-      insert_at_head( &tnl->dfn_cache.Color4ub, dfn );
-      dfn->key = key;
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 18, 0x0, (int)tnl->ubytecolorptr); 
-      FIXUP(dfn->code, 24, 0x0, (int)tnl->ubytecolorptr+1); 
-      FIXUP(dfn->code, 30, 0x0, (int)tnl->ubytecolorptr+2); 
-      FIXUP(dfn->code, 36, 0x0, (int)tnl->ubytecolorptr+3); 
-      return dfn;
-   }
-   else
-      return 0;
-}
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _tnl_x86_Attribute4fv, tnl->vtx.cache.Attribute[4-1], dest );
 
+   FIXUP(dfn->code, 0, 0, dest); 
+   FIXUP(dfn->code, 0, 1, 4+dest); 
+   FIXUP(dfn->code, 0, 2, 8+dest);
+   FIXUP(dfn->code, 0, 3, 12+dest);
 
-struct dynfn *tnl_makeX86Color3fv( TNLcontext *tnl, int key )
-{
-   if (key & (TNL_CP_VC_FRMT_PKCOLOR|TNL_CP_VC_FRMT_FPALPHA))
-      return 0;
-   else
-   {
-      static  char temp[] = {
-        0x8b, 0x44, 0x24, 0x04,                /* mov    0x4(%esp,1),%eax */
-        0xba, 0, 0, 0, 0,              /* mov    $DEST,%edx */
-        0x8b, 0x08,                    /* mov    (%eax),%ecx */
-        0x89, 0x0a,                    /* mov    %ecx,(%edx) */
-        0x8b, 0x48, 0x04,              /* mov    0x4(%eax),%ecx */
-        0x89, 0x4a, 0x04,              /* mov    %ecx,0x4(%edx) */
-        0x8b, 0x48, 0x08,              /* mov    0x8(%eax),%ecx */
-        0x89, 0x4a, 0x08,              /* mov    %ecx,0x8(%edx) */
-        0xc3,                          /* ret    */
-      };
-
-      struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-      if (TNL_DEBUG & DEBUG_CODEGEN)
-        fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-      insert_at_head( &tnl->dfn_cache.Color3fv, dfn );
-      dfn->key = key;
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 5, 0x0, (int)tnl->floatcolorptr); 
-      return dfn;
-   }
+   return dfn;
 }
 
-struct dynfn *tnl_makeX86Color3f( TNLcontext *tnl, int key )
+
+void _tnl_InitX86Codegen( struct _tnl_dynfn_generators *gen )
 {
-   if (key & (TNL_CP_VC_FRMT_PKCOLOR|TNL_CP_VC_FRMT_FPALPHA))
-      return 0;
-   else
-   {
-      static  char temp[] = {
-        0xba, 0x78, 0x56, 0x34, 0x12,          /*  mov    $DEST,%edx */
-        0x8b, 0x44, 0x24, 0x04,                /*  mov    0x4(%esp,1),%eax */
-        0x89, 0x02,                    /*  mov    %eax,(%edx) */
-        0x8b, 0x44, 0x24, 0x08,                /*  mov    0x8(%esp,1),%eax */
-        0x89, 0x42, 0x04,              /*  mov    %eax,0x4(%edx) */
-        0x8b, 0x44, 0x24, 0x0c,                /*  mov    0xc(%esp,1),%eax */
-        0x89, 0x42, 0x08,              /*  mov    %eax,0x8(%edx) */
-        0xc3,                          /*  ret     */
-      };
-
-      struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-      if (TNL_DEBUG & DEBUG_CODEGEN)
-        fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-      insert_at_head( &tnl->dfn_cache.Color3f, dfn );
-      dfn->key = key;
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 1, 0x12345678, (int)tnl->floatcolorptr); 
-      return dfn;
-   }
+   gen->Vertex[0] = makeX86Vertex1fv;
+   gen->Vertex[1] = makeX86Vertex2fv;
+   gen->Vertex[2] = makeX86Vertex3fv;
+   gen->Vertex[3] = makeX86Vertex4fv;
+   gen->Attribute[0] = makeX86Attribute1fv;
+   gen->Attribute[1] = makeX86Attribute2fv;
+   gen->Attribute[2] = makeX86Attribute3fv;
+   gen->Attribute[3] = makeX86Attribute4fv;
 }
 
 
+#define MKDISP(FUNC, SIZE, ATTR, WARP)                                 \
+do {                                                                   \
+   char *code;                                                         \
+   char *start = (char *)&WARP;                                                \
+   char *end = (char *)&WARP##_end;                                    \
+   int offset = 0;                                                     \
+   code = ALIGN_MALLOC( end - start, 16 );                             \
+   memcpy (code, start, end - start);                                  \
+   FIXUP(code, 0, 0, (int)&(TNL_CONTEXT(ctx)->vtx.tabfv[ATTR][SIZE-1]));\
+   *(void **)&vfmt->FUNC = code;                                       \
+} while (0)
 
-struct dynfn *tnl_makeX86TexCoord2fv( TNLcontext *tnl, int key )
-{
-   static  char temp[] = {
-      0x8b, 0x44, 0x24, 0x04,                  /* mov    0x4(%esp,1),%eax */
-      0xba, 0x78, 0x56, 0x34, 0x12,     /* mov    $DEST,%edx */
-      0x8b, 0x08,                      /* mov    (%eax),%ecx */
-      0x8b, 0x40, 0x04,                /* mov    0x4(%eax),%eax */
-      0x89, 0x0a,                      /* mov    %ecx,(%edx) */
-      0x89, 0x42, 0x04,                /* mov    %eax,0x4(%edx) */
-      0xc3,                            /* ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]); 
-   return dfn;
-}
 
-struct dynfn *tnl_makeX86TexCoord2f( TNLcontext *tnl, int key )
+/* Install the codegen'ed versions of the 2nd level dispatch
+ * functions.  We should keep a list and free them in the end...
+ */
+void _tnl_x86_exec_vtxfmt_init( GLcontext *ctx )
 {
-   static  char temp[] = {
-      0xba, 0x78, 0x56, 0x34, 0x12,            /* mov    $DEST,%edx */
-      0x8b, 0x44, 0x24, 0x04,                  /* mov    0x4(%esp,1),%eax */
-      0x8b, 0x4c, 0x24, 0x08,                  /* mov    0x8(%esp,1),%ecx */
-      0x89, 0x02,                      /* mov    %eax,(%edx) */
-      0x89, 0x4a, 0x04,                /* mov    %ecx,0x4(%edx) */
-      0xc3,                            /* ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]); 
-   return dfn;
+   GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->exec_vtxfmt);
+
+   MKDISP(Color3f,             3, _TNL_ATTRIB_COLOR0, _tnl_x86_dispatch_attrf3);
+   MKDISP(Color3fv,            3, _TNL_ATTRIB_COLOR0, _tnl_x86_dispatch_attrfv);
+   MKDISP(Color4f,             4, _TNL_ATTRIB_COLOR0, _tnl_x86_dispatch_attrf4);
+   MKDISP(Color4fv,            4, _TNL_ATTRIB_COLOR0, _tnl_x86_dispatch_attrfv);
+   MKDISP(FogCoordfEXT,        1, _TNL_ATTRIB_FOG,    _tnl_x86_dispatch_attrf1);
+   MKDISP(FogCoordfvEXT,       1, _TNL_ATTRIB_FOG,    _tnl_x86_dispatch_attrfv);
+   MKDISP(Normal3f,            3, _TNL_ATTRIB_NORMAL, _tnl_x86_dispatch_attrf3);
+   MKDISP(Normal3fv,           3, _TNL_ATTRIB_NORMAL, _tnl_x86_dispatch_attrfv);
+   MKDISP(SecondaryColor3fEXT, 3, _TNL_ATTRIB_COLOR1, _tnl_x86_dispatch_attrf3);
+   MKDISP(SecondaryColor3fvEXT,3, _TNL_ATTRIB_COLOR1, _tnl_x86_dispatch_attrfv);
+   MKDISP(TexCoord1f,          1, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_attrf1);
+   MKDISP(TexCoord1fv,         1, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_attrfv);
+   MKDISP(TexCoord2f,          2, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_attrf2);
+   MKDISP(TexCoord2fv,         2, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_attrfv);
+   MKDISP(TexCoord3f,          3, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_attrf3);
+   MKDISP(TexCoord3fv,         3, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_attrfv);
+   MKDISP(TexCoord4f,          4, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_attrf4);
+   MKDISP(TexCoord4fv,         4, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_attrfv);
+   MKDISP(Vertex2f,            2, _TNL_ATTRIB_POS,    _tnl_x86_dispatch_attrf2);
+   MKDISP(Vertex2fv,           2, _TNL_ATTRIB_POS,    _tnl_x86_dispatch_attrfv);
+   MKDISP(Vertex3f,            3, _TNL_ATTRIB_POS,    _tnl_x86_dispatch_attrf3);
+   MKDISP(Vertex3fv,           3, _TNL_ATTRIB_POS,    _tnl_x86_dispatch_attrfv);
+   MKDISP(Vertex4f,            4, _TNL_ATTRIB_POS,    _tnl_x86_dispatch_attrf4);
+   MKDISP(Vertex4fv,           4, _TNL_ATTRIB_POS,    _tnl_x86_dispatch_attrfv);
+
+   MKDISP(MultiTexCoord1fARB,  1, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_multitexcoordf1);
+   MKDISP(MultiTexCoord1fvARB, 1, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_multitexcoordfv);
+   MKDISP(MultiTexCoord2fARB,  2, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_multitexcoordf2);
+   MKDISP(MultiTexCoord2fvARB, 2, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_multitexcoordfv);
+   MKDISP(MultiTexCoord3fARB,  3, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_multitexcoordf3);
+   MKDISP(MultiTexCoord3fvARB, 3, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_multitexcoordfv);
+   MKDISP(MultiTexCoord4fARB,  4, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_multitexcoordf4);
+   MKDISP(MultiTexCoord4fvARB, 4, _TNL_ATTRIB_TEX0,   _tnl_x86_dispatch_multitexcoordfv);
+
+   MKDISP(VertexAttrib1fNV,    1, 0,                  _tnl_x86_dispatch_vertexattribf1);
+   MKDISP(VertexAttrib1fvNV,   1, 0,                  _tnl_x86_dispatch_vertexattribfv);
+   MKDISP(VertexAttrib2fNV,    2, 0,                  _tnl_x86_dispatch_vertexattribf2);
+   MKDISP(VertexAttrib2fvNV,   2, 0,                  _tnl_x86_dispatch_vertexattribfv);
+   MKDISP(VertexAttrib3fNV,    3, 0,                  _tnl_x86_dispatch_vertexattribf3);
+   MKDISP(VertexAttrib3fvNV,   3, 0,                  _tnl_x86_dispatch_vertexattribfv);
+   MKDISP(VertexAttrib4fNV,    4, 0,                  _tnl_x86_dispatch_vertexattribf4);
+   MKDISP(VertexAttrib4fvNV,   4, 0,                  _tnl_x86_dispatch_vertexattribfv);
 }
 
-struct dynfn *tnl_makeX86MultiTexCoord2fvARB( TNLcontext *tnl, int key )
+
+/* Install the codegen'ed choosers.
+ * We should keep a list and free them in the end...
+ */
+void _tnl_x86choosers( tnl_attrfv_func (*choose)[4],
+                      tnl_attrfv_func (*do_choose)( GLuint attr,
+                                                GLuint sz ))
 {
-   static  char temp[] = {
-      0x8b, 0x44, 0x24, 0x04,                  /* mov    0x4(%esp,1),%eax */
-      0x8b, 0x4c, 0x24, 0x08,                  /* mov    0x8(%esp,1),%ecx */
-      0x2d, 0xc0, 0x84, 0x00, 0x00,            /* sub    $0x84c0,%eax */
-      0x83, 0xe0, 0x01,                /* and    $0x1,%eax */
-      0x8b, 0x11,                      /* mov    (%ecx),%edx */
-      0xc1, 0xe0, 0x03,                /* shl    $0x3,%eax */
-      0x8b, 0x49, 0x04,                /* mov    0x4(%ecx),%ecx */
-      0x89, 0x90, 0, 0, 0, 0,/* mov    %edx,DEST(%eax) */
-      0x89, 0x88, 0, 0, 0, 0,/* mov    %ecx,DEST+8(%eax) */
-      0xc3,                            /* ret     */
-   };
-
-   static char temp2[] = {
-      0x8b, 0x44, 0x24, 0x04,                  /* mov    0x4(%esp,1),%eax */
-      0x8b, 0x4c, 0x24, 0x08,                  /* mov    0x8(%esp,1),%ecx */
-      0x2d, 0xc0, 0x84, 0x00, 0x00,            /* sub    $0x84c0,%eax */
-      0x83, 0xe0, 0x01,                /* and    $0x1,%eax */
-      0x8b, 0x14, 0x85, 0, 0, 0, 0, /* mov    DEST(,%eax,4),%edx */
-      0x8b, 0x01,                      /* mov    (%ecx),%eax */
-      0x89, 0x02,                      /* mov    %eax,(%edx) */
-      0x8b, 0x41, 0x04,                /* mov    0x4(%ecx),%eax */
-      0x89, 0x42, 0x04,                /* mov    %eax,0x4(%edx) */
-      0xc3,                            /* ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.MultiTexCoord2fvARB, dfn );
-   dfn->key = key;
-
-   if ((key & (TNL_CP_VC_FRMT_ST0|TNL_CP_VC_FRMT_ST1)) ==
-      (TNL_CP_VC_FRMT_ST0|TNL_CP_VC_FRMT_ST1)) {
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 26, 0x0, (int)tnl->texcoordptr[0]);     
-      FIXUP(dfn->code, 32, 0x0, (int)tnl->texcoordptr[0]+4);
-   } else {
-      dfn->code = ALIGN_MALLOC( sizeof(temp2), 16 );
-      memcpy (dfn->code, temp2, sizeof(temp2));
-      FIXUP(dfn->code, 19, 0x0, (int)tnl->texcoordptr);
+   int attr, size;
+
+   for (attr = 0; attr < _TNL_MAX_ATTR_CODEGEN; attr++) {
+      for (size = 0; size < 4; size++) {
+         char *code;
+         char *start = (char *)&_tnl_x86_choose_fv;
+         char *end = (char *)&_tnl_x86_choose_fv_end;
+         int offset = 0;
+         code = ALIGN_MALLOC( end - start, 16 );
+         memcpy (code, start, end - start);
+         FIXUP(code, 0, 0, attr);
+         FIXUP(code, 0, 1, size + 1);
+         FIXUPREL(code, 0, 2, do_choose);
+         choose[attr][size] = (tnl_attrfv_func)code;
+      }
    }
-   return dfn;
 }
 
-struct dynfn *tnl_makeX86MultiTexCoord2fARB( TNLcontext *tnl, 
-                                               int key )
+#else 
+
+void _tnl_InitX86Codegen( struct _tnl_dynfn_generators *gen )
 {
-   static  char temp[] = {
-      0x8b, 0x44, 0x24, 0x04,                  /* mov    0x4(%esp,1),%eax */
-      0x8b, 0x54, 0x24, 0x08,                  /* mov    0x8(%esp,1),%edx */
-      0x2d, 0xc0, 0x84, 0x00, 0x00,            /* sub    $0x84c0,%eax */
-      0x8b, 0x4c, 0x24, 0x0c,                  /* mov    0xc(%esp,1),%ecx */
-      0x83, 0xe0, 0x01,                /* and    $0x1,%eax */
-      0xc1, 0xe0, 0x03,                /* shl    $0x3,%eax */
-      0x89, 0x90, 0, 0, 0, 0,  /* mov    %edx,DEST(%eax) */
-      0x89, 0x88, 0, 0, 0, 0,  /* mov    %ecx,DEST+8(%eax) */
-      0xc3,                            /* ret     */
-   };
-
-   static char temp2[] = {
-      0x8b, 0x44, 0x24, 0x04,                  /* mov    0x4(%esp,1),%eax */
-      0x8b, 0x54, 0x24, 0x08,                  /* mov    0x8(%esp,1),%edx */
-      0x2d, 0xc0, 0x84, 0x00, 0x00,            /* sub    $0x84c0,%eax */
-      0x8b, 0x4c, 0x24, 0x0c,                  /* mov    0xc(%esp,1),%ecx */
-      0x83, 0xe0, 0x01,                /* and    $0x1,%eax */
-      0x8b, 0x04, 0x85, 0, 0, 0, 0,     /* mov    DEST(,%eax,4),%eax */
-      0x89, 0x10,                      /* mov    %edx,(%eax) */
-      0x89, 0x48, 0x04,                /* mov    %ecx,0x4(%eax) */
-      0xc3,                            /* ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.MultiTexCoord2fARB, dfn );
-   dfn->key = key;
-
-   if ((key & (TNL_CP_VC_FRMT_ST0|TNL_CP_VC_FRMT_ST1)) ==
-       (TNL_CP_VC_FRMT_ST0|TNL_CP_VC_FRMT_ST1)) {
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 25, 0x0, (int)tnl->texcoordptr[0]); 
-      FIXUP(dfn->code, 31, 0x0, (int)tnl->texcoordptr[0]+4); 
-   }
-   else {
-      /* Note: this might get generated multiple times, even though the
-       * actual emitted code is the same.
-       */
-      dfn->code = ALIGN_MALLOC( sizeof(temp2), 16 );
-      memcpy (dfn->code, temp2, sizeof(temp2));
-      FIXUP(dfn->code, 23, 0x0, (int)tnl->texcoordptr); 
-   }      
-   return dfn;
+   (void) gen;
 }
 
 
-void _tnl_InitX86Codegen( struct dfn_generators *gen )
+void _tnl_x86_exec_vtxfmt_init( GLcontext *ctx )
 {
-   gen->Vertex3f = tnl_makeX86Vertex3f;
-   gen->Vertex3fv = tnl_makeX86Vertex3fv;
-   gen->Color4ub = tnl_makeX86Color4ub; /* PKCOLOR only */
-   gen->Color4ubv = tnl_makeX86Color4ubv; /* PKCOLOR only */
-   gen->Normal3f = tnl_makeX86Normal3f;
-   gen->Normal3fv = tnl_makeX86Normal3fv;
-   gen->TexCoord2f = tnl_makeX86TexCoord2f;
-   gen->TexCoord2fv = tnl_makeX86TexCoord2fv;
-   gen->MultiTexCoord2fARB = tnl_makeX86MultiTexCoord2fARB;
-   gen->MultiTexCoord2fvARB = tnl_makeX86MultiTexCoord2fvARB;
-   gen->Color3f = tnl_makeX86Color3f;
-   gen->Color3fv = tnl_makeX86Color3fv;
-
-   /* Not done:
-    */
-/*     gen->Vertex2f = tnl_makeX86Vertex2f; */
-/*     gen->Vertex2fv = tnl_makeX86Vertex2fv; */
-/*     gen->Color3ub = tnl_makeX86Color3ub; */
-/*     gen->Color3ubv = tnl_makeX86Color3ubv; */
-/*     gen->Color4f = tnl_makeX86Color4f; */
-/*     gen->Color4fv = tnl_makeX86Color4fv; */
-/*     gen->TexCoord1f = tnl_makeX86TexCoord1f; */
-/*     gen->TexCoord1fv = tnl_makeX86TexCoord1fv; */
-/*     gen->MultiTexCoord1fARB = tnl_makeX86MultiTexCoord1fARB; */
-/*     gen->MultiTexCoord1fvARB = tnl_makeX86MultiTexCoord1fvARB; */
+   (void) ctx;
 }
 
 
-#else 
-
-void _tnl_InitX86Codegen( struct dfn_generators *gen )
+void _tnl_x86choosers( tnl_attrfv_func (*choose)[4],
+                      tnl_attrfv_func (*do_choose)( GLuint attr,
+                                                GLuint sz ))
 {
-   (void) gen;
+   (void) choose;
+   (void) do_choose;
 }
 
 #endif