1afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg/*
2afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * Mesa 3-D graphics library
33a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul * Version:  6.5.1
4fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes *
53a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes *
7afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * Permission is hereby granted, free of charge, to any person obtaining a
8afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * copy of this software and associated documentation files (the "Software"),
9afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * to deal in the Software without restriction, including without limitation
10afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * and/or sell copies of the Software, and to permit persons to whom the
12afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * Software is furnished to do so, subject to the following conditions:
13fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes *
14afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * The above copyright notice and this permission notice shall be included
15afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * in all copies or substantial portions of the Software.
16fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes *
17afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg */
24afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
2581f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick/**
2681f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick * \file common_x86.c
2781f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick *
28fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes * Check CPU capabilities & initialize optimized funtions for this particular
29fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes * processor.
30afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg *
3181f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick * Changed by Andre Werthmann for using the new SSE functions.
3281f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick *
3381f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick * \author Holger Waechtler <holger@akaflieg.extern.tu-berlin.de>
3481f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick * \author Andre Werthmann <wertmann@cs.uni-potsdam.de>
35afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg */
36afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
3720c831bb899301642e3b7f808315459a6126e731Brian Paul/* XXX these includes should probably go into imports.h or glheader.h */
381b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughes#if defined(USE_SSE_ASM) && defined(__linux__)
39663a3e9ba700c832bfaea1f2131a37c5505d1c25George Sapountzis#include <linux/version.h>
402ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes#endif
41902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul#if defined(USE_SSE_ASM) && defined(__FreeBSD__)
42902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul#include <sys/types.h>
43902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul#include <sys/sysctl.h>
44902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul#endif
45f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith#if defined(USE_SSE_ASM) && defined(__OpenBSD__)
46f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith#include <sys/param.h>
47f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith#include <sys/sysctl.h>
48f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith#include <machine/cpu.h>
49f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith#endif
50fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes
51bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/imports.h"
52fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes#include "common_x86_asm.h"
53fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes
54afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
55c751224b0acd457d99cead45616980fec7ef78f1Brian Paul/** Bitmask of X86_FEATURE_x bits */
56c751224b0acd457d99cead45616980fec7ef78f1Brian Paulint _mesa_x86_cpu_features = 0x0;
57c751224b0acd457d99cead45616980fec7ef78f1Brian Paul
58aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholtstatic int detection_debug = GL_FALSE;
59afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
60fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes/* No reason for this to be public.
61fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes */
629b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_has_cpuid(void);
63c329e5a3d81a56437de4e19fec1de3eca2a1afb7Kendall Bennettextern void	_ASMAPI _mesa_x86_cpuid(GLuint op, GLuint *reg_eax, GLuint *reg_ebx, GLuint *reg_ecx, GLuint *reg_edx);
649b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_cpuid_eax(GLuint op);
659b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_cpuid_ebx(GLuint op);
669b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_cpuid_ecx(GLuint op);
679b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_cpuid_edx(GLuint op);
68fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes
69d8aec9b55b0180384e96cddff48fc48751bbc320Brian Paul
701b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughes#if defined(USE_SSE_ASM)
712ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes/*
722ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes * We must verify that the Streaming SIMD Extensions are truly supported
732ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes * on this processor before we go ahead and hook out the optimized code.
7481f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick *
7581f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick * However, I have been told by Alan Cox that all 2.4 (and later) Linux
7681f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick * kernels provide full SSE support on all processors that expose SSE via
77663a3e9ba700c832bfaea1f2131a37c5505d1c25George Sapountzis * the CPUID mechanism.
782ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes */
79c751224b0acd457d99cead45616980fec7ef78f1Brian Paul
80c751224b0acd457d99cead45616980fec7ef78f1Brian Paul/* These are assembly functions: */
811b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughesextern void _mesa_test_os_sse_support( void );
821b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughesextern void _mesa_test_os_sse_exception_support( void );
832ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes
84c751224b0acd457d99cead45616980fec7ef78f1Brian Paul
85eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#if defined(WIN32)
86eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#ifndef STATUS_FLOAT_MULTIPLE_TRAPS
87eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul# define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L)
88eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#endif
89eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paulstatic LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS exp)
90eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul{
91eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   PEXCEPTION_RECORD rec = exp->ExceptionRecord;
92eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   PCONTEXT ctx = exp->ContextRecord;
93eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
94eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( rec->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION ) {
953a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "EXCEPTION_ILLEGAL_INSTRUCTION\n" );
96eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
97eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   } else if ( rec->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS ) {
983a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "STATUS_FLOAT_MULTIPLE_TRAPS\n");
99eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      /* Windows seems to clear the exception flag itself, we just have to increment Eip */
100eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   } else {
1013a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "UNEXPECTED EXCEPTION (0x%08x), terminating!\n" );
102eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      return EXCEPTION_EXECUTE_HANDLER;
103eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
104eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
105eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( (ctx->ContextFlags & CONTEXT_CONTROL) != CONTEXT_CONTROL ) {
1063a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Context does not contain control registers, terminating!\n");
107eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      return EXCEPTION_EXECUTE_HANDLER;
108eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
109eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   ctx->Eip += 3;
110eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
111eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   return EXCEPTION_CONTINUE_EXECUTION;
112eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul}
113eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#endif /* WIN32 */
114eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
115eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
116c751224b0acd457d99cead45616980fec7ef78f1Brian Paul/**
117c751224b0acd457d99cead45616980fec7ef78f1Brian Paul * Check if SSE is supported.
118c751224b0acd457d99cead45616980fec7ef78f1Brian Paul * If not, turn off the X86_FEATURE_XMM flag in _mesa_x86_cpu_features.
119c751224b0acd457d99cead45616980fec7ef78f1Brian Paul */
120c751224b0acd457d99cead45616980fec7ef78f1Brian Paulvoid _mesa_check_os_sse_support( void )
1212ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes{
12289f070b3bbb86204306857b8cf690abbd56a939dMichel Dänzer#if defined(__FreeBSD__)
123902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul   {
12438b317d508a2a3a4cc6d700ebca80c3b06c913e2Alan Hourihane      int ret, enabled;
12538b317d508a2a3a4cc6d700ebca80c3b06c913e2Alan Hourihane      unsigned int len;
126902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul      len = sizeof(enabled);
127902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul      ret = sysctlbyname("hw.instruction_sse", &enabled, &len, NULL, 0);
128902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul      if (ret || !enabled)
129902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
130902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul   }
131ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz#elif defined (__NetBSD__)
132ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz   {
133ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz      int ret, enabled;
134ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz      size_t len = sizeof(enabled);
135ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz      ret = sysctlbyname("machdep.sse", &enabled, &len, (void *)NULL, 0);
136ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz      if (ret || !enabled)
137ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
138ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz   }
139f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith#elif defined(__OpenBSD__)
140f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith   {
141f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      int mib[2];
142f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      int ret, enabled;
143f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      size_t len = sizeof(enabled);
144f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith
145f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      mib[0] = CTL_MACHDEP;
146f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      mib[1] = CPU_SSE;
147f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith
148f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      ret = sysctl(mib, 2, &enabled, &len, NULL, 0);
149f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      if (ret || !enabled)
150f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
151f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith   }
152eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#elif defined(WIN32)
153eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   LPTOP_LEVEL_EXCEPTION_FILTER oldFilter;
154eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
155eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   /* Install our ExceptionFilter */
156eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   oldFilter = SetUnhandledExceptionFilter( ExceptionFilter );
157eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
158eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( cpu_has_xmm ) {
1593a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Testing OS support for SSE...\n");
160eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
161eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      _mesa_test_os_sse_support();
162eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
163eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      if ( cpu_has_xmm ) {
1643a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul	 _mesa_debug(NULL, "Yes.\n");
165eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      } else {
1663a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul	 _mesa_debug(NULL, "No!\n");
167eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      }
168eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
169eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
170eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( cpu_has_xmm ) {
1713a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Testing OS support for SSE unmasked exceptions...\n");
172eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
173eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      _mesa_test_os_sse_exception_support();
174eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
175eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      if ( cpu_has_xmm ) {
1763a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul	 _mesa_debug(NULL, "Yes.\n");
177eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      } else {
1783a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul	 _mesa_debug(NULL, "No!\n");
179eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      }
180eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
181eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
182eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   /* Restore previous exception filter */
183eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   SetUnhandledExceptionFilter( oldFilter );
184eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
185eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( cpu_has_xmm ) {
1863a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Tests of OS support for SSE passed.\n");
187eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   } else {
1883a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Tests of OS support for SSE failed!\n");
189eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
1902ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes#else
191902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul   /* Do nothing on other platforms for now.
1922ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes    */
193aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt   if (detection_debug)
194aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt      _mesa_debug(NULL, "Not testing OS support for SSE, leaving enabled.\n");
19589f070b3bbb86204306857b8cf690abbd56a939dMichel Dänzer#endif /* __FreeBSD__ */
1962ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes}
1972ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes
1981b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughes#endif /* USE_SSE_ASM */
1992ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes
200afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
201c751224b0acd457d99cead45616980fec7ef78f1Brian Paul/**
202c751224b0acd457d99cead45616980fec7ef78f1Brian Paul * Initialize the _mesa_x86_cpu_features bitfield.
20316d72437eac3ea9c557424edfc98cd664f4c4ed3Brian Paul * This is a no-op if called more than once.
204c751224b0acd457d99cead45616980fec7ef78f1Brian Paul */
205c751224b0acd457d99cead45616980fec7ef78f1Brian Paulvoid
206c751224b0acd457d99cead45616980fec7ef78f1Brian Paul_mesa_get_x86_features(void)
207afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg{
20816d72437eac3ea9c557424edfc98cd664f4c4ed3Brian Paul   static int called = 0;
20916d72437eac3ea9c557424edfc98cd664f4c4ed3Brian Paul
21016d72437eac3ea9c557424edfc98cd664f4c4ed3Brian Paul   if (called)
21116d72437eac3ea9c557424edfc98cd664f4c4ed3Brian Paul      return;
21216d72437eac3ea9c557424edfc98cd664f4c4ed3Brian Paul
21316d72437eac3ea9c557424edfc98cd664f4c4ed3Brian Paul   called = 1;
21416d72437eac3ea9c557424edfc98cd664f4c4ed3Brian Paul
215afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg#ifdef USE_X86_ASM
216c751224b0acd457d99cead45616980fec7ef78f1Brian Paul   _mesa_x86_cpu_features = 0x0;
217c751224b0acd457d99cead45616980fec7ef78f1Brian Paul
218c751224b0acd457d99cead45616980fec7ef78f1Brian Paul   if (_mesa_getenv( "MESA_NO_ASM")) {
219c751224b0acd457d99cead45616980fec7ef78f1Brian Paul      return;
220c751224b0acd457d99cead45616980fec7ef78f1Brian Paul   }
221da54ffc852996f94dcf46b0cdc40c5ff12b55496Keith Whitwell
222068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul   if (!_mesa_x86_has_cpuid()) {
2233a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul       _mesa_debug(NULL, "CPUID not detected\n");
224068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul   }
225068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul   else {
226068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       GLuint cpu_features;
227068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       GLuint cpu_ext_features;
228068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       GLuint cpu_ext_info;
229068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       char cpu_vendor[13];
230068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       GLuint result;
231068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
232068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       /* get vendor name */
233068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       _mesa_x86_cpuid(0, &result, (GLuint *)(cpu_vendor + 0), (GLuint *)(cpu_vendor + 8), (GLuint *)(cpu_vendor + 4));
234068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       cpu_vendor[12] = '\0';
235068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
236aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt       if (detection_debug)
237aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt	  _mesa_debug(NULL, "CPU vendor: %s\n", cpu_vendor);
238068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
239068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       /* get cpu features */
240068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       cpu_features = _mesa_x86_cpuid_edx(1);
241068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
242068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_FPU)
243068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_FPU;
244068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_CMOV)
245068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_CMOV;
246068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
247068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#ifdef USE_MMX_ASM
248068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_MMX)
249068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_MMX;
250068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#endif
251068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
252068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#ifdef USE_SSE_ASM
253068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_XMM)
254068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_XMM;
255068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_XMM2)
256068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_XMM2;
257068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#endif
258068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
259068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       /* query extended cpu features */
260068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if ((cpu_ext_info = _mesa_x86_cpuid_eax(0x80000000)) > 0x80000000) {
261068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   if (cpu_ext_info >= 0x80000001) {
262068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
263068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       cpu_ext_features = _mesa_x86_cpuid_edx(0x80000001);
264068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
265068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       if (cpu_features & X86_CPU_MMX) {
266068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
267068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#ifdef USE_3DNOW_ASM
268068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		   if (cpu_ext_features & X86_CPUEXT_3DNOW)
269068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		       _mesa_x86_cpu_features |= X86_FEATURE_3DNOW;
270068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		   if (cpu_ext_features & X86_CPUEXT_3DNOW_EXT)
271068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		       _mesa_x86_cpu_features |= X86_FEATURE_3DNOWEXT;
272068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#endif
273068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
274068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#ifdef USE_MMX_ASM
275068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		   if (cpu_ext_features & X86_CPUEXT_MMX_EXT)
276068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		       _mesa_x86_cpu_features |= X86_FEATURE_MMXEXT;
277068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#endif
278068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       }
279068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   }
280068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
281068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   /* query cpu name */
282068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   if (cpu_ext_info >= 0x80000002) {
283068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       GLuint ofs;
284068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       char cpu_name[49];
285068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       for (ofs = 0; ofs < 3; ofs++)
286068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		   _mesa_x86_cpuid(0x80000002+ofs, (GLuint *)(cpu_name + (16*ofs)+0), (GLuint *)(cpu_name + (16*ofs)+4), (GLuint *)(cpu_name + (16*ofs)+8), (GLuint *)(cpu_name + (16*ofs)+12));
287068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       cpu_name[48] = '\0'; /* the name should be NULL terminated, but just to be sure */
288068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
289aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt	       if (detection_debug)
290aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt		  _mesa_debug(NULL, "CPU name: %s\n", cpu_name);
291068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   }
292068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       }
293068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
294068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul   }
2957af8f7f164dba479de25aed835c890db39351d8dEric Anholt
2967af8f7f164dba479de25aed835c890db39351d8dEric Anholt#ifdef USE_MMX_ASM
2977af8f7f164dba479de25aed835c890db39351d8dEric Anholt   if ( cpu_has_mmx ) {
2987af8f7f164dba479de25aed835c890db39351d8dEric Anholt      if ( _mesa_getenv( "MESA_NO_MMX" ) == 0 ) {
299aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt	 if (detection_debug)
300aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt	    _mesa_debug(NULL, "MMX cpu detected.\n");
3017af8f7f164dba479de25aed835c890db39351d8dEric Anholt      } else {
3027af8f7f164dba479de25aed835c890db39351d8dEric Anholt         _mesa_x86_cpu_features &= ~(X86_FEATURE_MMX);
3037af8f7f164dba479de25aed835c890db39351d8dEric Anholt      }
3047af8f7f164dba479de25aed835c890db39351d8dEric Anholt   }
3057af8f7f164dba479de25aed835c890db39351d8dEric Anholt#endif
3067af8f7f164dba479de25aed835c890db39351d8dEric Anholt
3077af8f7f164dba479de25aed835c890db39351d8dEric Anholt#ifdef USE_3DNOW_ASM
3087af8f7f164dba479de25aed835c890db39351d8dEric Anholt   if ( cpu_has_3dnow ) {
3097af8f7f164dba479de25aed835c890db39351d8dEric Anholt      if ( _mesa_getenv( "MESA_NO_3DNOW" ) == 0 ) {
310aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt	 if (detection_debug)
311aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt	    _mesa_debug(NULL, "3DNow! cpu detected.\n");
3127af8f7f164dba479de25aed835c890db39351d8dEric Anholt      } else {
3137af8f7f164dba479de25aed835c890db39351d8dEric Anholt         _mesa_x86_cpu_features &= ~(X86_FEATURE_3DNOW);
3147af8f7f164dba479de25aed835c890db39351d8dEric Anholt      }
3157af8f7f164dba479de25aed835c890db39351d8dEric Anholt   }
3167af8f7f164dba479de25aed835c890db39351d8dEric Anholt#endif
3177af8f7f164dba479de25aed835c890db39351d8dEric Anholt
3187af8f7f164dba479de25aed835c890db39351d8dEric Anholt#ifdef USE_SSE_ASM
3197af8f7f164dba479de25aed835c890db39351d8dEric Anholt   if ( cpu_has_xmm ) {
3207af8f7f164dba479de25aed835c890db39351d8dEric Anholt      if ( _mesa_getenv( "MESA_NO_SSE" ) == 0 ) {
321aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt	 if (detection_debug)
322aa2f55883b9a4e8a192c5dcc97ae7fdab2a33e0aEric Anholt	    _mesa_debug(NULL, "SSE cpu detected.\n");
3237af8f7f164dba479de25aed835c890db39351d8dEric Anholt         if ( _mesa_getenv( "MESA_FORCE_SSE" ) == 0 ) {
3247af8f7f164dba479de25aed835c890db39351d8dEric Anholt            _mesa_check_os_sse_support();
3257af8f7f164dba479de25aed835c890db39351d8dEric Anholt         }
3267af8f7f164dba479de25aed835c890db39351d8dEric Anholt      } else {
3277af8f7f164dba479de25aed835c890db39351d8dEric Anholt         _mesa_debug(NULL, "SSE cpu detected, but switched off by user.\n");
3287af8f7f164dba479de25aed835c890db39351d8dEric Anholt         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
3297af8f7f164dba479de25aed835c890db39351d8dEric Anholt      }
3307af8f7f164dba479de25aed835c890db39351d8dEric Anholt   }
3317af8f7f164dba479de25aed835c890db39351d8dEric Anholt#endif
3327af8f7f164dba479de25aed835c890db39351d8dEric Anholt
333c751224b0acd457d99cead45616980fec7ef78f1Brian Paul#endif /* USE_X86_ASM */
3349ea2a3af9c3e150e212f2bcbb23ae05b4779d702Vinson Lee
3359ea2a3af9c3e150e212f2bcbb23ae05b4779d702Vinson Lee   (void) detection_debug;
336afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg}
337