i965: Fix nested loops in the VS.
[mesa.git] / src / mesa / glapi / glapi_getproc.c
index 6d40b495c7e71424d264bcba09d354c67e556a21..a6dbf173e82d98228ef4008df5fdbdf30eb2500b 100644 (file)
  */
 
 /**
- * \file glapi_getproc.
+ * \file glapi_getproc.c
  *
  * Code for implementing glXGetProcAddress(), etc.
  * This was originally in glapi.c but refactored out.
  */
 
 
-#include <stdlib.h>
-#include <string.h>
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#include "glapi/mesa.h"
+#else
 #include "main/glheader.h"
-#include "glapi.h"
-#include "glapioffsets.h"
-#include "glapitable.h"
-
-
-static void
-fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset);
-
-
-/**
- * strdup() is actually not a standard ANSI C or POSIX routine.
- * Irix will not define it if ANSI mode is in effect.
- */
-static char *
-str_dup(const char *str)
-{
-   char *copy;
-   copy = (char*) malloc(strlen(str) + 1);
-   if (!copy)
-      return NULL;
-   strcpy(copy, str);
-   return copy;
-}
+#include "main/compiler.h"
+#endif
 
+#include "glapi/glapi.h"
+#include "glapi/glapioffsets.h"
+#include "glapi/glapitable.h"
 
 
 #if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS)
@@ -74,7 +58,7 @@ str_dup(const char *str)
 #endif
 
 /* The code in this file is auto-generated with Python */
-#include "glprocs.h"
+#include "glapi/glprocs.h"
 
 
 /**
@@ -87,7 +71,13 @@ find_entry( const char * n )
    GLuint i;
    for (i = 0; static_functions[i].Name_offset >= 0; i++) {
       const char *testName = gl_string_table + static_functions[i].Name_offset;
-      if (strcmp(testName, n) == 0) {
+#ifdef MANGLE
+      /* skip the "m" prefix on the name */
+      if (strcmp(testName, n + 1) == 0)
+#else
+      if (strcmp(testName, n) == 0)
+#endif
+      {
         return &static_functions[i];
       }
    }
@@ -110,7 +100,6 @@ get_static_proc_offset(const char *funcName)
 }
 
 
-#if !defined(XFree86Server) && !defined(XGLServer)
 #ifdef USE_X86_ASM
 
 #if defined( GLX_USE_TLS )
@@ -123,6 +112,8 @@ extern const GLubyte gl_dispatch_functions_start[];
 #endif /* USE_X86_ASM */
 
 
+#if !defined(XFree86Server) && !defined(XGLServer)
+
 /**
  * Return dispatch function address for the named static (built-in) function.
  * Return NULL if function not found.
@@ -171,6 +162,172 @@ get_static_proc_name( GLuint offset )
 
 
 
+#if defined(PTHREADS) || defined(GLX_USE_TLS)
+
+/**
+ * Perform platform-specific GL API entry-point fixups.
+ */
+static void
+init_glapi_relocs( void )
+{
+#if defined(USE_X86_ASM) && defined(GLX_USE_TLS) && !defined(GLX_X86_READONLY_TEXT)
+    extern unsigned long _x86_get_dispatch(void);
+    char run_time_patch[] = {
+       0x65, 0xa1, 0, 0, 0, 0 /* movl %gs:0,%eax */
+    };
+    GLuint *offset = (GLuint *) &run_time_patch[2]; /* 32-bits for x86/32 */
+    const GLubyte * const get_disp = (const GLubyte *) run_time_patch;
+    GLubyte * curr_func = (GLubyte *) gl_dispatch_functions_start;
+
+    *offset = _x86_get_dispatch();
+    while ( curr_func != (GLubyte *) gl_dispatch_functions_end ) {
+       (void) memcpy( curr_func, get_disp, sizeof(run_time_patch));
+       curr_func += DISPATCH_FUNCTION_SIZE;
+    }
+#endif
+#ifdef USE_SPARC_ASM
+    extern void __glapi_sparc_icache_flush(unsigned int *);
+    static const unsigned int template[] = {
+#ifdef GLX_USE_TLS
+       0x05000000, /* sethi %hi(_glapi_tls_Dispatch), %g2 */
+       0x8730e00a, /* srl %g3, 10, %g3 */
+       0x8410a000, /* or %g2, %lo(_glapi_tls_Dispatch), %g2 */
+#ifdef __arch64__
+       0xc259c002, /* ldx [%g7 + %g2], %g1 */
+       0xc2584003, /* ldx [%g1 + %g3], %g1 */
+#else
+       0xc201c002, /* ld [%g7 + %g2], %g1 */
+       0xc2004003, /* ld [%g1 + %g3], %g1 */
+#endif
+       0x81c04000, /* jmp %g1 */
+       0x01000000, /* nop  */
+#else
+#ifdef __arch64__
+       0x03000000, /* 64-bit 0x00 --> sethi %hh(_glapi_Dispatch), %g1 */
+       0x05000000, /* 64-bit 0x04 --> sethi %lm(_glapi_Dispatch), %g2 */
+       0x82106000, /* 64-bit 0x08 --> or %g1, %hm(_glapi_Dispatch), %g1 */
+       0x8730e00a, /* 64-bit 0x0c --> srl %g3, 10, %g3 */
+       0x83287020, /* 64-bit 0x10 --> sllx %g1, 32, %g1 */
+       0x82004002, /* 64-bit 0x14 --> add %g1, %g2, %g1 */
+       0xc2586000, /* 64-bit 0x18 --> ldx [%g1 + %lo(_glapi_Dispatch)], %g1 */
+#else
+       0x03000000, /* 32-bit 0x00 --> sethi %hi(_glapi_Dispatch), %g1 */
+       0x8730e00a, /* 32-bit 0x04 --> srl %g3, 10, %g3 */
+       0xc2006000, /* 32-bit 0x08 --> ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
+#endif
+       0x80a06000, /*             --> cmp %g1, 0 */
+       0x02800005, /*             --> be +4*5 */
+       0x01000000, /*             -->  nop  */
+#ifdef __arch64__
+       0xc2584003, /* 64-bit      --> ldx [%g1 + %g3], %g1 */
+#else
+       0xc2004003, /* 32-bit      --> ld [%g1 + %g3], %g1 */
+#endif
+       0x81c04000, /*             --> jmp %g1 */
+       0x01000000, /*             --> nop  */
+#ifdef __arch64__
+       0x9de3bf80, /* 64-bit      --> save  %sp, -128, %sp */
+#else
+       0x9de3bfc0, /* 32-bit      --> save  %sp, -64, %sp */
+#endif
+       0xa0100003, /*             --> mov  %g3, %l0 */
+       0x40000000, /*             --> call _glapi_get_dispatch */
+       0x01000000, /*             -->  nop */
+       0x82100008, /*             --> mov %o0, %g1 */
+       0x86100010, /*             --> mov %l0, %g3 */
+       0x10bffff7, /*             --> ba -4*9 */
+       0x81e80000, /*             -->  restore  */
+#endif
+    };
+#ifdef GLX_USE_TLS
+    extern unsigned int __glapi_sparc_tls_stub;
+    extern unsigned long __glapi_sparc_get_dispatch(void);
+    unsigned int *code = &__glapi_sparc_tls_stub;
+    unsigned long dispatch = __glapi_sparc_get_dispatch();
+#else
+    extern unsigned int __glapi_sparc_pthread_stub;
+    unsigned int *code = &__glapi_sparc_pthread_stub;
+    unsigned long dispatch = (unsigned long) &_glapi_Dispatch;
+    unsigned long call_dest = (unsigned long ) &_glapi_get_dispatch;
+    int idx;
+#endif
+
+#if defined(GLX_USE_TLS)
+    code[0] = template[0] | (dispatch >> 10);
+    code[1] = template[1];
+    __glapi_sparc_icache_flush(&code[0]);
+    code[2] = template[2] | (dispatch & 0x3ff);
+    code[3] = template[3];
+    __glapi_sparc_icache_flush(&code[2]);
+    code[4] = template[4];
+    code[5] = template[5];
+    __glapi_sparc_icache_flush(&code[4]);
+    code[6] = template[6];
+    __glapi_sparc_icache_flush(&code[6]);
+#else
+#if defined(__arch64__)
+    code[0] = template[0] | (dispatch >> (32 + 10));
+    code[1] = template[1] | ((dispatch & 0xffffffff) >> 10);
+    __glapi_sparc_icache_flush(&code[0]);
+    code[2] = template[2] | ((dispatch >> 32) & 0x3ff);
+    code[3] = template[3];
+    __glapi_sparc_icache_flush(&code[2]);
+    code[4] = template[4];
+    code[5] = template[5];
+    __glapi_sparc_icache_flush(&code[4]);
+    code[6] = template[6] | (dispatch & 0x3ff);
+    idx = 7;
+#else
+    code[0] = template[0] | (dispatch >> 10);
+    code[1] = template[1];
+    __glapi_sparc_icache_flush(&code[0]);
+    code[2] = template[2] | (dispatch & 0x3ff);
+    idx = 3;
+#endif
+    code[idx + 0] = template[idx + 0];
+    __glapi_sparc_icache_flush(&code[idx - 1]);
+    code[idx + 1] = template[idx + 1];
+    code[idx + 2] = template[idx + 2];
+    __glapi_sparc_icache_flush(&code[idx + 1]);
+    code[idx + 3] = template[idx + 3];
+    code[idx + 4] = template[idx + 4];
+    __glapi_sparc_icache_flush(&code[idx + 3]);
+    code[idx + 5] = template[idx + 5];
+    code[idx + 6] = template[idx + 6];
+    __glapi_sparc_icache_flush(&code[idx + 5]);
+    code[idx + 7] = template[idx + 7];
+    code[idx + 8] = template[idx + 8] |
+           (((call_dest - ((unsigned long) &code[idx + 8]))
+             >> 2) & 0x3fffffff);
+    __glapi_sparc_icache_flush(&code[idx + 7]);
+    code[idx + 9] = template[idx + 9];
+    code[idx + 10] = template[idx + 10];
+    __glapi_sparc_icache_flush(&code[idx + 9]);
+    code[idx + 11] = template[idx + 11];
+    code[idx + 12] = template[idx + 12];
+    __glapi_sparc_icache_flush(&code[idx + 11]);
+    code[idx + 13] = template[idx + 13];
+    __glapi_sparc_icache_flush(&code[idx + 13]);
+#endif
+#endif
+}
+
+void
+init_glapi_relocs_once( void )
+{
+   static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+   pthread_once( & once_control, init_glapi_relocs );
+}
+
+#else
+
+void
+init_glapi_relocs_once( void ) { }
+
+#endif /* defined(PTHREADS) || defined(GLX_USE_TLS) */
+
+
+
 /**********************************************************************
  * Extension function management.
  */
@@ -228,6 +385,9 @@ static GLuint NumExtEntryPoints = 0;
 extern void __glapi_sparc_icache_flush(unsigned int *);
 #endif
 
+static void
+fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset);
+
 /**
  * Generate a dispatch function (entrypoint) which jumps through
  * the given slot number (offset) in the current dispatch table.
@@ -254,53 +414,34 @@ generate_entrypoint(GLuint functionOffset)
    return (_glapi_proc) code;
 #elif defined(USE_SPARC_ASM)
 
-#ifdef __arch64__
-   static const unsigned int insn_template[] = {
-          0x05000000,  /* sethi        %uhi(_glapi_Dispatch), %g2      */
-          0x03000000,  /* sethi        %hi(_glapi_Dispatch), %g1       */
-          0x8410a000,  /* or           %g2, %ulo(_glapi_Dispatch), %g2 */
-          0x82106000,  /* or           %g1, %lo(_glapi_Dispatch), %g1  */
-          0x8528b020,  /* sllx         %g2, 32, %g2                    */
-          0xc2584002,  /* ldx          [%g1 + %g2], %g1                */
-          0x05000000,  /* sethi        %hi(8 * glapioffset), %g2       */
-          0x8410a000,  /* or           %g2, %lo(8 * glapioffset), %g2  */
-          0xc6584002,  /* ldx          [%g1 + %g2], %g3                */
-          0x81c0c000,  /* jmpl         %g3, %g0                        */
-          0x01000000   /*  nop                                         */
+#if defined(PTHREADS) || defined(GLX_USE_TLS)
+   static const unsigned int template[] = {
+      0x07000000, /* sethi %hi(0), %g3 */
+      0x8210000f, /* mov  %o7, %g1 */
+      0x40000000, /* call */
+      0x9e100001, /* mov  %g1, %o7 */
    };
+#ifdef GLX_USE_TLS
+   extern unsigned int __glapi_sparc_tls_stub;
+   unsigned long call_dest = (unsigned long ) &__glapi_sparc_tls_stub;
 #else
-   static const unsigned int insn_template[] = {
-          0x03000000,  /* sethi        %hi(_glapi_Dispatch), %g1         */
-          0xc2006000,  /* ld           [%g1 + %lo(_glapi_Dispatch)], %g1 */
-          0xc6006000,  /* ld           [%g1 + %lo(4*glapioffset)], %g3   */
-          0x81c0c000,  /* jmpl         %g3, %g0                          */
-          0x01000000   /*  nop                                           */
-   };
-#endif /* __arch64__ */
-   unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
-   unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
+   extern unsigned int __glapi_sparc_pthread_stub;
+   unsigned long call_dest = (unsigned long ) &__glapi_sparc_pthread_stub;
+#endif
+   unsigned int *code = (unsigned int *) malloc(sizeof(template));
    if (code) {
-      memcpy(code, insn_template, sizeof(insn_template));
-
-#ifdef __arch64__
-      code[0] |= (glapi_addr >> (32 + 10));
-      code[1] |= ((glapi_addr & 0xffffffff) >> 10);
-      __glapi_sparc_icache_flush(&code[0]);
-      code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
-      code[3] |= (glapi_addr & ((1 << 10) - 1));
-      __glapi_sparc_icache_flush(&code[2]);
-      code[6] |= ((functionOffset * 8) >> 10);
-      code[7] |= ((functionOffset * 8) & ((1 << 10) - 1));
-      __glapi_sparc_icache_flush(&code[6]);
-#else
-      code[0] |= (glapi_addr >> 10);
-      code[1] |= (glapi_addr & ((1 << 10) - 1));
+      code[0] = template[0] | (functionOffset & 0x3fffff);
+      code[1] = template[1];
       __glapi_sparc_icache_flush(&code[0]);
-      code[2] |= (functionOffset * 4);
+      code[2] = template[2] |
+         (((call_dest - ((unsigned long) &code[2]))
+          >> 2) & 0x3fffffff);
+      code[3] = template[3];
       __glapi_sparc_icache_flush(&code[2]);
-#endif /* __arch64__ */
    }
    return (_glapi_proc) code;
+#endif
+
 #else
    (void) functionOffset;
    return NULL;
@@ -330,21 +471,10 @@ fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
 #endif
 
 #elif defined(USE_SPARC_ASM)
-
-   /* XXX this hasn't been tested! */
    unsigned int *code = (unsigned int *) entrypoint;
-#ifdef __arch64__
-   code[6] = 0x05000000;  /* sethi     %hi(8 * glapioffset), %g2       */
-   code[7] = 0x8410a000;  /* or                %g2, %lo(8 * glapioffset), %g2  */
-   code[6] |= ((offset * 8) >> 10);
-   code[7] |= ((offset * 8) & ((1 << 10) - 1));
-   __glapi_sparc_icache_flush(&code[6]);
-#else /* __arch64__ */
-   code[2] = 0xc6006000;  /* ld                [%g1 + %lo(4*glapioffset)], %g3   */
-   code[2] |= (offset * 4);
-   __glapi_sparc_icache_flush(&code[2]);
-#endif /* __arch64__ */
-
+   code[0] &= ~0x3fffff;
+   code[0] |= (offset * sizeof(void *)) & 0x3fffff;
+   __glapi_sparc_icache_flush(&code[0]);
 #else
 
    /* an unimplemented architecture */
@@ -355,6 +485,22 @@ fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
 }
 
 
+/**
+ * strdup() is actually not a standard ANSI C or POSIX routine.
+ * Irix will not define it if ANSI mode is in effect.
+ */
+static char *
+str_dup(const char *str)
+{
+   char *copy;
+   copy = (char*) malloc(strlen(str) + 1);
+   if (!copy)
+      return NULL;
+   strcpy(copy, str);
+   return copy;
+}
+
+
 /**
  * Generate new entrypoint
  *
@@ -557,7 +703,7 @@ _glapi_get_proc_offset(const char *funcName)
  * in the name of static functions, try generating a new API entrypoint on
  * the fly with assembly language.
  */
-_glapi_proc
+PUBLIC _glapi_proc
 _glapi_get_proc_address(const char *funcName)
 {
    struct _glapi_function * entry;
@@ -617,3 +763,74 @@ _glapi_get_proc_name(GLuint offset)
    }
    return NULL;
 }
+
+
+
+/**
+ * Do some spot checks to be sure that the dispatch table
+ * slots are assigned correctly. For debugging only.
+ */
+void
+_glapi_check_table(const struct _glapi_table *table)
+{
+#if 0 /* enable this for extra DEBUG */
+   {
+      GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
+      char *BeginFunc = (char*) &table->Begin;
+      GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
+      assert(BeginOffset == _gloffset_Begin);
+      assert(BeginOffset == offset);
+   }
+   {
+      GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
+      char *viewportFunc = (char*) &table->Viewport;
+      GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
+      assert(viewportOffset == _gloffset_Viewport);
+      assert(viewportOffset == offset);
+   }
+   {
+      GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
+      char *VertexPointerFunc = (char*) &table->VertexPointer;
+      GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
+      assert(VertexPointerOffset == _gloffset_VertexPointer);
+      assert(VertexPointerOffset == offset);
+   }
+   {
+      GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
+      char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
+      GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
+      assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
+      assert(ResetMinMaxOffset == offset);
+   }
+   {
+      GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
+      char *blendColorFunc = (char*) &table->BlendColor;
+      GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
+      assert(blendColorOffset == _gloffset_BlendColor);
+      assert(blendColorOffset == offset);
+   }
+   {
+      GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
+      char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
+      GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
+      assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
+      assert(secondaryColor3fOffset == offset);
+   }
+   {
+      GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
+      char *pointParameterivFunc = (char*) &table->PointParameterivNV;
+      GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
+      assert(pointParameterivOffset == _gloffset_PointParameterivNV);
+      assert(pointParameterivOffset == offset);
+   }
+   {
+      GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
+      char *setFenceFunc = (char*) &table->SetFenceNV;
+      GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
+      assert(setFenceOffset == _gloffset_SetFenceNV);
+      assert(setFenceOffset == offset);
+   }
+#else
+   (void) table;
+#endif
+}