michael@0: /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* compile-time and runtime tests for whether to use SSE instructions */ michael@0: michael@0: #include "SSE.h" michael@0: michael@0: namespace { michael@0: michael@0: // SSE.h has parallel #ifs which declare MOZILLA_SSE_HAVE_CPUID_DETECTION. michael@0: // We can't declare these functions in the header file, however, because michael@0: // conflicts with on MSVC 2005, and some files want to michael@0: // include both SSE.h and . michael@0: michael@0: #ifdef HAVE_CPUID_H michael@0: michael@0: // cpuid.h is available on gcc 4.3 and higher on i386 and x86_64 michael@0: #include michael@0: michael@0: enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 }; michael@0: michael@0: static bool michael@0: has_cpuid_bit(unsigned int level, CPUIDRegister reg, unsigned int bit) michael@0: { michael@0: unsigned int regs[4]; michael@0: return __get_cpuid(level, ®s[0], ®s[1], ®s[2], ®s[3]) && michael@0: (regs[reg] & bit); michael@0: } michael@0: michael@0: #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64)) michael@0: michael@0: // MSVC 2005 or newer on x86-32 or x86-64 michael@0: #include michael@0: michael@0: enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 }; michael@0: michael@0: static bool michael@0: has_cpuid_bit(unsigned int level, CPUIDRegister reg, unsigned int bit) michael@0: { michael@0: // Check that the level in question is supported. michael@0: int regs[4]; michael@0: __cpuid(regs, level & 0x80000000u); michael@0: if (unsigned(regs[0]) < level) michael@0: return false; michael@0: michael@0: __cpuid(regs, level); michael@0: return !!(unsigned(regs[reg]) & bit); michael@0: } michael@0: michael@0: #elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__)) michael@0: michael@0: enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 }; michael@0: michael@0: #ifdef __i386 michael@0: static void michael@0: moz_cpuid(int CPUInfo[4], int InfoType) michael@0: { michael@0: asm ( michael@0: "xchg %esi, %ebx\n" michael@0: "cpuid\n" michael@0: "movl %eax, (%edi)\n" michael@0: "movl %ebx, 4(%edi)\n" michael@0: "movl %ecx, 8(%edi)\n" michael@0: "movl %edx, 12(%edi)\n" michael@0: "xchg %esi, %ebx\n" michael@0: : michael@0: : "a"(InfoType), // %eax michael@0: "D"(CPUInfo) // %edi michael@0: : "%ecx", "%edx", "%esi" michael@0: ); michael@0: } michael@0: #else michael@0: static void michael@0: moz_cpuid(int CPUInfo[4], int InfoType) michael@0: { michael@0: asm ( michael@0: "xchg %rsi, %rbx\n" michael@0: "cpuid\n" michael@0: "movl %eax, (%rdi)\n" michael@0: "movl %ebx, 4(%rdi)\n" michael@0: "movl %ecx, 8(%rdi)\n" michael@0: "movl %edx, 12(%rdi)\n" michael@0: "xchg %rsi, %rbx\n" michael@0: : michael@0: : "a"(InfoType), // %eax michael@0: "D"(CPUInfo) // %rdi michael@0: : "%ecx", "%edx", "%rsi" michael@0: ); michael@0: } michael@0: #endif michael@0: michael@0: static bool michael@0: has_cpuid_bit(unsigned int level, CPUIDRegister reg, unsigned int bit) michael@0: { michael@0: // Check that the level in question is supported. michael@0: volatile int regs[4]; michael@0: moz_cpuid((int *)regs, level & 0x80000000u); michael@0: if (unsigned(regs[0]) < level) michael@0: return false; michael@0: michael@0: moz_cpuid((int *)regs, level); michael@0: return !!(unsigned(regs[reg]) & bit); michael@0: } michael@0: michael@0: #endif // end CPUID declarations michael@0: michael@0: } michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace sse_private { michael@0: michael@0: #if defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) michael@0: michael@0: #if !defined(MOZILLA_PRESUME_MMX) michael@0: bool mmx_enabled = has_cpuid_bit(1u, edx, (1u<<23)); michael@0: #endif michael@0: michael@0: #if !defined(MOZILLA_PRESUME_SSE) michael@0: bool sse_enabled = has_cpuid_bit(1u, edx, (1u<<25)); michael@0: #endif michael@0: michael@0: #if !defined(MOZILLA_PRESUME_SSE2) michael@0: bool sse2_enabled = has_cpuid_bit(1u, edx, (1u<<26)); michael@0: #endif michael@0: michael@0: #if !defined(MOZILLA_PRESUME_SSE3) michael@0: bool sse3_enabled = has_cpuid_bit(1u, ecx, (1u<<0)); michael@0: #endif michael@0: michael@0: #if !defined(MOZILLA_PRESUME_SSSE3) michael@0: bool ssse3_enabled = has_cpuid_bit(1u, ecx, (1u<<9)); michael@0: #endif michael@0: michael@0: #if !defined(MOZILLA_PRESUME_SSE4A) michael@0: bool sse4a_enabled = has_cpuid_bit(0x80000001u, ecx, (1u<<6)); michael@0: #endif michael@0: michael@0: #if !defined(MOZILLA_PRESUME_SSE4_1) michael@0: bool sse4_1_enabled = has_cpuid_bit(1u, ecx, (1u<<19)); michael@0: #endif michael@0: michael@0: #if !defined(MOZILLA_PRESUME_SSE4_2) michael@0: bool sse4_2_enabled = has_cpuid_bit(1u, ecx, (1u<<20)); michael@0: #endif michael@0: michael@0: #endif michael@0: michael@0: } // namespace sse_private michael@0: } // namespace mozilla