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