common_x86.c revision f49d345a51bb208fee19fc25762bcdb0e7f67174
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
51fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes#include "common_x86_asm.h"
5262d821786c2b80f6b2a663f106a39e69116b02d5Brian Paul#include "imports.h"
53fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes
54afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
55865322f931197c5c73c57b366b64300894565dabBrian Paulint _mesa_x86_cpu_features = 0;
56afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
57fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes/* No reason for this to be public.
58fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes */
599b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_has_cpuid(void);
60c329e5a3d81a56437de4e19fec1de3eca2a1afb7Kendall Bennettextern void	_ASMAPI _mesa_x86_cpuid(GLuint op, GLuint *reg_eax, GLuint *reg_ebx, GLuint *reg_ecx, GLuint *reg_edx);
619b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_cpuid_eax(GLuint op);
629b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_cpuid_ebx(GLuint op);
639b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_cpuid_ecx(GLuint op);
649b77fb7dab3fd4e4a9228e5c0609cc494aa01211Kendall Bennettextern GLuint	_ASMAPI _mesa_x86_cpuid_edx(GLuint op);
65fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes
66d8aec9b55b0180384e96cddff48fc48751bbc320Brian Paul
671b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughes#if defined(USE_SSE_ASM)
682ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes/*
692ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes * We must verify that the Streaming SIMD Extensions are truly supported
702ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes * on this processor before we go ahead and hook out the optimized code.
7181f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick *
7281f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick * However, I have been told by Alan Cox that all 2.4 (and later) Linux
7381f67fc4e9621f08f46c8219f5ab5dc5c329b146Ian Romanick * kernels provide full SSE support on all processors that expose SSE via
74663a3e9ba700c832bfaea1f2131a37c5505d1c25George Sapountzis * the CPUID mechanism.
752ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes */
761b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughesextern void _mesa_test_os_sse_support( void );
771b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughesextern void _mesa_test_os_sse_exception_support( void );
782ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes
79eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#if defined(WIN32)
80eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#ifndef STATUS_FLOAT_MULTIPLE_TRAPS
81eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul# define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L)
82eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#endif
83eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paulstatic LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS exp)
84eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul{
85eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   PEXCEPTION_RECORD rec = exp->ExceptionRecord;
86eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   PCONTEXT ctx = exp->ContextRecord;
87eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
88eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( rec->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION ) {
893a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "EXCEPTION_ILLEGAL_INSTRUCTION\n" );
90eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
91eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   } else if ( rec->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS ) {
923a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "STATUS_FLOAT_MULTIPLE_TRAPS\n");
93eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      /* Windows seems to clear the exception flag itself, we just have to increment Eip */
94eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   } else {
953a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "UNEXPECTED EXCEPTION (0x%08x), terminating!\n" );
96eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      return EXCEPTION_EXECUTE_HANDLER;
97eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
98eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
99eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( (ctx->ContextFlags & CONTEXT_CONTROL) != CONTEXT_CONTROL ) {
1003a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Context does not contain control registers, terminating!\n");
101eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      return EXCEPTION_EXECUTE_HANDLER;
102eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
103eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   ctx->Eip += 3;
104eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
105eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   return EXCEPTION_CONTINUE_EXECUTION;
106eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul}
107eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#endif /* WIN32 */
108eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
109eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
1101b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughesstatic void check_os_sse_support( void )
1112ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes{
11289f070b3bbb86204306857b8cf690abbd56a939dMichel Dänzer#if defined(__FreeBSD__)
113902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul   {
11438b317d508a2a3a4cc6d700ebca80c3b06c913e2Alan Hourihane      int ret, enabled;
11538b317d508a2a3a4cc6d700ebca80c3b06c913e2Alan Hourihane      unsigned int len;
116902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul      len = sizeof(enabled);
117902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul      ret = sysctlbyname("hw.instruction_sse", &enabled, &len, NULL, 0);
118902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul      if (ret || !enabled)
119902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
120902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul   }
121ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz#elif defined (__NetBSD__)
122ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz   {
123ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz      int ret, enabled;
124ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz      size_t len = sizeof(enabled);
125ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz      ret = sysctlbyname("machdep.sse", &enabled, &len, (void *)NULL, 0);
126ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz      if (ret || !enabled)
127ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
128ece7183ff1b1bba1ae8e41b143e2ccbc38376dc3Blair Sadewitz   }
129f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith#elif defined(__OpenBSD__)
130f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith   {
131f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      int mib[2];
132f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      int ret, enabled;
133f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      size_t len = sizeof(enabled);
134f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith
135f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      mib[0] = CTL_MACHDEP;
136f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      mib[1] = CPU_SSE;
137f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith
138f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      ret = sysctl(mib, 2, &enabled, &len, NULL, 0);
139f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith      if (ret || !enabled)
140f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
141f49d345a51bb208fee19fc25762bcdb0e7f67174Brad Smith   }
142eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul#elif defined(WIN32)
143eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   LPTOP_LEVEL_EXCEPTION_FILTER oldFilter;
144eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
145eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   /* Install our ExceptionFilter */
146eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   oldFilter = SetUnhandledExceptionFilter( ExceptionFilter );
147eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
148eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( cpu_has_xmm ) {
1493a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Testing OS support for SSE...\n");
150eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
151eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      _mesa_test_os_sse_support();
152eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
153eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      if ( cpu_has_xmm ) {
1543a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul	 _mesa_debug(NULL, "Yes.\n");
155eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      } else {
1563a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul	 _mesa_debug(NULL, "No!\n");
157eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      }
158eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
159eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
160eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( cpu_has_xmm ) {
1613a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Testing OS support for SSE unmasked exceptions...\n");
162eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
163eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      _mesa_test_os_sse_exception_support();
164eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
165eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      if ( cpu_has_xmm ) {
1663a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul	 _mesa_debug(NULL, "Yes.\n");
167eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      } else {
1683a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul	 _mesa_debug(NULL, "No!\n");
169eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul      }
170eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
171eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
172eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   /* Restore previous exception filter */
173eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   SetUnhandledExceptionFilter( oldFilter );
174eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul
175eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   if ( cpu_has_xmm ) {
1763a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Tests of OS support for SSE passed.\n");
177eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   } else {
1783a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul      _mesa_debug(NULL, "Tests of OS support for SSE failed!\n");
179eaf2b170fffbd573ca8482a7dfa30af24f39a4a1Brian Paul   }
1802ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes#else
181902d2faadf37a5627ab2cbcd8993825c8749ec82Brian Paul   /* Do nothing on other platforms for now.
1822ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes    */
1833a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul   _mesa_debug(NULL, "Not testing OS support for SSE, leaving enabled.\n");
18489f070b3bbb86204306857b8cf690abbd56a939dMichel Dänzer#endif /* __FreeBSD__ */
1852ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes}
1862ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes
1871b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughes#endif /* USE_SSE_ASM */
1882ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes
189afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
19008836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paulvoid _mesa_init_all_x86_transform_asm( void )
191afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg{
192afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg#ifdef USE_X86_ASM
193068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul   _mesa_x86_cpu_features = 0;
194da54ffc852996f94dcf46b0cdc40c5ff12b55496Keith Whitwell
195068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul   if (!_mesa_x86_has_cpuid()) {
1963a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul       _mesa_debug(NULL, "CPUID not detected\n");
197068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul   }
198068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul   else {
199068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       GLuint cpu_features;
200068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       GLuint cpu_ext_features;
201068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       GLuint cpu_ext_info;
202068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       char cpu_vendor[13];
203068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       GLuint result;
204068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
205068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       /* get vendor name */
206068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       _mesa_x86_cpuid(0, &result, (GLuint *)(cpu_vendor + 0), (GLuint *)(cpu_vendor + 8), (GLuint *)(cpu_vendor + 4));
207068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       cpu_vendor[12] = '\0';
208068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
2093a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul       _mesa_debug(NULL, "CPU vendor: %s\n", cpu_vendor);
210068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
211068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       /* get cpu features */
212068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       cpu_features = _mesa_x86_cpuid_edx(1);
213068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
214068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_FPU)
215068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_FPU;
216068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_CMOV)
217068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_CMOV;
218068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
219068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#ifdef USE_MMX_ASM
220068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_MMX)
221068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_MMX;
222068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#endif
223068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
224068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#ifdef USE_SSE_ASM
225068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_XMM)
226068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_XMM;
227068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if (cpu_features & X86_CPU_XMM2)
228068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   _mesa_x86_cpu_features |= X86_FEATURE_XMM2;
229068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#endif
230068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
231068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       /* query extended cpu features */
232068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       if ((cpu_ext_info = _mesa_x86_cpuid_eax(0x80000000)) > 0x80000000) {
233068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   if (cpu_ext_info >= 0x80000001) {
234068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
235068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       cpu_ext_features = _mesa_x86_cpuid_edx(0x80000001);
236068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
237068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       if (cpu_features & X86_CPU_MMX) {
238068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
239068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#ifdef USE_3DNOW_ASM
240068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		   if (cpu_ext_features & X86_CPUEXT_3DNOW)
241068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		       _mesa_x86_cpu_features |= X86_FEATURE_3DNOW;
242068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		   if (cpu_ext_features & X86_CPUEXT_3DNOW_EXT)
243068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		       _mesa_x86_cpu_features |= X86_FEATURE_3DNOWEXT;
244068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#endif
245068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
246068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#ifdef USE_MMX_ASM
247068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		   if (cpu_ext_features & X86_CPUEXT_MMX_EXT)
248068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul		       _mesa_x86_cpu_features |= X86_FEATURE_MMXEXT;
249068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul#endif
250068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       }
251068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   }
252068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
253068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   /* query cpu name */
254068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   if (cpu_ext_info >= 0x80000002) {
255068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       GLuint ofs;
256068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       char cpu_name[49];
257068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       for (ofs = 0; ofs < 3; ofs++)
258068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian 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));
259068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	       cpu_name[48] = '\0'; /* the name should be NULL terminated, but just to be sure */
260068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
2613a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul	       _mesa_debug(NULL, "CPU name: %s\n", cpu_name);
262068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul	   }
263068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul       }
264068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
265068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul   }
266068a4812fc1d9e321aa65a91ceb8bc824bedc69aBrian Paul
26720c831bb899301642e3b7f808315459a6126e731Brian Paul   if ( _mesa_getenv( "MESA_NO_ASM" ) ) {
268865322f931197c5c73c57b366b64300894565dabBrian Paul      _mesa_x86_cpu_features = 0;
269afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg   }
270afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
271865322f931197c5c73c57b366b64300894565dabBrian Paul   if ( _mesa_x86_cpu_features ) {
27208836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul      _mesa_init_x86_transform_asm();
273da54ffc852996f94dcf46b0cdc40c5ff12b55496Keith Whitwell   }
274afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
275afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg#ifdef USE_MMX_ASM
276fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes   if ( cpu_has_mmx ) {
27720c831bb899301642e3b7f808315459a6126e731Brian Paul      if ( _mesa_getenv( "MESA_NO_MMX" ) == 0 ) {
2783a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul         _mesa_debug(NULL, "MMX cpu detected.\n");
279afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg      } else {
280865322f931197c5c73c57b366b64300894565dabBrian Paul         _mesa_x86_cpu_features &= ~(X86_FEATURE_MMX);
281afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg      }
282afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg   }
283afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg#endif
284afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
285afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg#ifdef USE_3DNOW_ASM
286fc2427e81b1c648550d0368652d6a475df785027Gareth Hughes   if ( cpu_has_3dnow ) {
28720c831bb899301642e3b7f808315459a6126e731Brian Paul      if ( _mesa_getenv( "MESA_NO_3DNOW" ) == 0 ) {
2883a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul         _mesa_debug(NULL, "3DNow! cpu detected.\n");
28908836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul         _mesa_init_3dnow_transform_asm();
290afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg      } else {
291865322f931197c5c73c57b366b64300894565dabBrian Paul         _mesa_x86_cpu_features &= ~(X86_FEATURE_3DNOW);
292afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg      }
293afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg   }
294afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg#endif
295afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
2961b2fef5c28a40cd001598071e25b876ad4fccdd1Gareth Hughes#ifdef USE_SSE_ASM
2972ac44e2509dff861d50239d3248c60bf08f3ed92Gareth Hughes   if ( cpu_has_xmm ) {
29859c2e16e755c0cba78b27525681cd79456a2f496Daniel Borca      if ( _mesa_getenv( "MESA_NO_SSE" ) == 0 ) {
2993a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul         _mesa_debug(NULL, "SSE cpu detected.\n");
30059c2e16e755c0cba78b27525681cd79456a2f496Daniel Borca         if ( _mesa_getenv( "MESA_FORCE_SSE" ) == 0 ) {
30159c2e16e755c0cba78b27525681cd79456a2f496Daniel Borca            check_os_sse_support();
30259c2e16e755c0cba78b27525681cd79456a2f496Daniel Borca         }
30359c2e16e755c0cba78b27525681cd79456a2f496Daniel Borca         if ( cpu_has_xmm ) {
30459c2e16e755c0cba78b27525681cd79456a2f496Daniel Borca            _mesa_init_sse_transform_asm();
30559c2e16e755c0cba78b27525681cd79456a2f496Daniel Borca         }
3066630e2be01f41fb3b0fdf815e00a82d8e980f116Andre Werthmann      } else {
3073a5ec72125075cbb59eda5c6ed6672524f4b48b3Brian Paul         _mesa_debug(NULL, "SSE cpu detected, but switched off by user.\n");
308865322f931197c5c73c57b366b64300894565dabBrian Paul         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
3096630e2be01f41fb3b0fdf815e00a82d8e980f116Andre Werthmann      }
3106630e2be01f41fb3b0fdf815e00a82d8e980f116Andre Werthmann   }
3116630e2be01f41fb3b0fdf815e00a82d8e980f116Andre Werthmann#endif
312afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg#endif
313afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg}
314afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cjtg
315