Use 3Dnow! x86-64 routines only on processors that support 3Dnow!
authorIan Romanick <ian.d.romanick@intel.com>
Mon, 29 Sep 2008 03:31:46 +0000 (20:31 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Mon, 29 Sep 2008 03:32:05 +0000 (20:32 -0700)
Added an x86-64 CPUID function and use it to detect 3Dnow!  If 3Dnow!
is available, use _mesa_3dnow_transform_points4_3d_no_rot,
_mesa_3dnow_transform_points4_perspective,
_mesa_3dnow_transform_points4_2d_no_rot, and _mesa_3dnow_transform_points4_2d.

This fixes long standing bug #8724.

src/mesa/x86-64/x86-64.c
src/mesa/x86-64/xform4.S

index 9ec43c8..96f8da8 100644 (file)
 #include "math/m_debug.h"
 #endif
 
+extern void _mesa_x86_64_cpuid(unsigned int *regs);
+
 DECLARE_XFORM_GROUP( x86_64, 4 )
+DECLARE_XFORM_GROUP( 3dnow, 4 )
 
 #else
 /* just to silence warning below */
@@ -81,6 +84,7 @@ static void message( const char *msg )
 void _mesa_init_all_x86_64_transform_asm(void)
 {
 #ifdef USE_X86_64_ASM
+   unsigned int regs[4];
 
    if ( _mesa_getenv( "MESA_NO_ASM" ) ) {
      return;
@@ -88,24 +92,32 @@ void _mesa_init_all_x86_64_transform_asm(void)
 
    message("Initializing x86-64 optimizations\n");
 
-   ASSIGN_XFORM_GROUP( x86_64, 4 );
 
-   /*
    _mesa_transform_tab[4][MATRIX_GENERAL] =
       _mesa_x86_64_transform_points4_general;
    _mesa_transform_tab[4][MATRIX_IDENTITY] =
       _mesa_x86_64_transform_points4_identity;
    _mesa_transform_tab[4][MATRIX_3D] =
       _mesa_x86_64_transform_points4_3d;
-   _mesa_transform_tab[4][MATRIX_3D_NO_ROT] =
-      _mesa_x86_64_transform_points4_3d_no_rot;
-   _mesa_transform_tab[4][MATRIX_PERSPECTIVE] =
-      _mesa_x86_64_transform_points4_perspective;
-   _mesa_transform_tab[4][MATRIX_2D_NO_ROT] =
-      _mesa_x86_64_transform_points4_2d_no_rot;
-   _mesa_transform_tab[4][MATRIX_2D] =
-      _mesa_x86_64_transform_points4_2d;
-   */
+
+   regs[0] = 0x80000001;
+   regs[1] = 0x00000000;
+   regs[2] = 0x00000000;
+   regs[3] = 0x00000000;
+   _mesa_x86_64_cpuid(regs);
+   if (regs[3] & (1U << 31)) {
+      message("3Dnow! detected\n");
+      _mesa_transform_tab[4][MATRIX_3D_NO_ROT] =
+         _mesa_3dnow_transform_points4_3d_no_rot;
+      _mesa_transform_tab[4][MATRIX_PERSPECTIVE] =
+         _mesa_3dnow_transform_points4_perspective;
+      _mesa_transform_tab[4][MATRIX_2D_NO_ROT] =
+         _mesa_3dnow_transform_points4_2d_no_rot;
+      _mesa_transform_tab[4][MATRIX_2D] =
+         _mesa_3dnow_transform_points4_2d;
+
+   }
+
    
 #ifdef DEBUG_MATH
    _math_test_all_transform_functions("x86_64");
index 3f9c9d5..8059691 100644 (file)
 .text
 
 .align 16
+.globl _mesa_x86_64_cpuid
+_mesa_x86_64_cpuid:
+       pushq   %rbx
+       movl    (%rdi), %eax
+       movl    8(%rdi), %ecx
+
+       cpuid
+
+       movl    %ebx, 4(%rdi)
+       movl    %eax, (%rdi)
+       movl    %ecx, 8(%rdi)
+       movl    %edx, 12(%rdi)
+       popq    %rbx
+       ret
 
+.align 16
 .globl _mesa_x86_64_transform_points4_general
 _mesa_x86_64_transform_points4_general:
 /*
@@ -204,8 +219,8 @@ p4_identity_done:
 
        
 .align 16
-.globl _mesa_x86_64_transform_points4_3d_no_rot
-_mesa_x86_64_transform_points4_3d_no_rot:
+.globl _mesa_3dnow_transform_points4_3d_no_rot
+_mesa_3dnow_transform_points4_3d_no_rot:
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
        movzx V4F_STRIDE(%rdx), %eax    /* stride */
@@ -268,8 +283,8 @@ p4_3d_no_rot_done:
 
        
 .align 16
-.globl _mesa_x86_64_transform_points4_perspective
-_mesa_x86_64_transform_points4_perspective:
+.globl _mesa_3dnow_transform_points4_perspective
+_mesa_3dnow_transform_points4_perspective:
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
        movzx V4F_STRIDE(%rdx), %eax    /* stride */
@@ -334,8 +349,8 @@ p4_perspective_done:
        ret
 
 .align 16
-.globl _mesa_x86_64_transform_points4_2d_no_rot
-_mesa_x86_64_transform_points4_2d_no_rot:
+.globl _mesa_3dnow_transform_points4_2d_no_rot
+_mesa_3dnow_transform_points4_2d_no_rot:
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
        movzx V4F_STRIDE(%rdx), %eax    /* stride */
@@ -389,8 +404,8 @@ p4_2d_no_rot_done:
 
        
 .align 16
-.globl _mesa_x86_64_transform_points4_2d
-_mesa_x86_64_transform_points4_2d:
+.globl _mesa_3dnow_transform_points4_2d
+_mesa_3dnow_transform_points4_2d:
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
        movzx V4F_STRIDE(%rdx), %eax    /* stride */