|
1 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* compile-time and runtime tests for whether to use SSE instructions */ |
|
7 |
|
8 #include "SSE.h" |
|
9 |
|
10 namespace { |
|
11 |
|
12 // SSE.h has parallel #ifs which declare MOZILLA_SSE_HAVE_CPUID_DETECTION. |
|
13 // We can't declare these functions in the header file, however, because |
|
14 // <intrin.h> conflicts with <windows.h> on MSVC 2005, and some files want to |
|
15 // include both SSE.h and <windows.h>. |
|
16 |
|
17 #ifdef HAVE_CPUID_H |
|
18 |
|
19 // cpuid.h is available on gcc 4.3 and higher on i386 and x86_64 |
|
20 #include <cpuid.h> |
|
21 |
|
22 enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 }; |
|
23 |
|
24 static bool |
|
25 has_cpuid_bit(unsigned int level, CPUIDRegister reg, unsigned int bit) |
|
26 { |
|
27 unsigned int regs[4]; |
|
28 return __get_cpuid(level, ®s[0], ®s[1], ®s[2], ®s[3]) && |
|
29 (regs[reg] & bit); |
|
30 } |
|
31 |
|
32 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64)) |
|
33 |
|
34 // MSVC 2005 or newer on x86-32 or x86-64 |
|
35 #include <intrin.h> |
|
36 |
|
37 enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 }; |
|
38 |
|
39 static bool |
|
40 has_cpuid_bit(unsigned int level, CPUIDRegister reg, unsigned int bit) |
|
41 { |
|
42 // Check that the level in question is supported. |
|
43 int regs[4]; |
|
44 __cpuid(regs, level & 0x80000000u); |
|
45 if (unsigned(regs[0]) < level) |
|
46 return false; |
|
47 |
|
48 __cpuid(regs, level); |
|
49 return !!(unsigned(regs[reg]) & bit); |
|
50 } |
|
51 |
|
52 #elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__)) |
|
53 |
|
54 enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 }; |
|
55 |
|
56 #ifdef __i386 |
|
57 static void |
|
58 moz_cpuid(int CPUInfo[4], int InfoType) |
|
59 { |
|
60 asm ( |
|
61 "xchg %esi, %ebx\n" |
|
62 "cpuid\n" |
|
63 "movl %eax, (%edi)\n" |
|
64 "movl %ebx, 4(%edi)\n" |
|
65 "movl %ecx, 8(%edi)\n" |
|
66 "movl %edx, 12(%edi)\n" |
|
67 "xchg %esi, %ebx\n" |
|
68 : |
|
69 : "a"(InfoType), // %eax |
|
70 "D"(CPUInfo) // %edi |
|
71 : "%ecx", "%edx", "%esi" |
|
72 ); |
|
73 } |
|
74 #else |
|
75 static void |
|
76 moz_cpuid(int CPUInfo[4], int InfoType) |
|
77 { |
|
78 asm ( |
|
79 "xchg %rsi, %rbx\n" |
|
80 "cpuid\n" |
|
81 "movl %eax, (%rdi)\n" |
|
82 "movl %ebx, 4(%rdi)\n" |
|
83 "movl %ecx, 8(%rdi)\n" |
|
84 "movl %edx, 12(%rdi)\n" |
|
85 "xchg %rsi, %rbx\n" |
|
86 : |
|
87 : "a"(InfoType), // %eax |
|
88 "D"(CPUInfo) // %rdi |
|
89 : "%ecx", "%edx", "%rsi" |
|
90 ); |
|
91 } |
|
92 #endif |
|
93 |
|
94 static bool |
|
95 has_cpuid_bit(unsigned int level, CPUIDRegister reg, unsigned int bit) |
|
96 { |
|
97 // Check that the level in question is supported. |
|
98 volatile int regs[4]; |
|
99 moz_cpuid((int *)regs, level & 0x80000000u); |
|
100 if (unsigned(regs[0]) < level) |
|
101 return false; |
|
102 |
|
103 moz_cpuid((int *)regs, level); |
|
104 return !!(unsigned(regs[reg]) & bit); |
|
105 } |
|
106 |
|
107 #endif // end CPUID declarations |
|
108 |
|
109 } |
|
110 |
|
111 namespace mozilla { |
|
112 |
|
113 namespace sse_private { |
|
114 |
|
115 #if defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
116 |
|
117 #if !defined(MOZILLA_PRESUME_MMX) |
|
118 bool mmx_enabled = has_cpuid_bit(1u, edx, (1u<<23)); |
|
119 #endif |
|
120 |
|
121 #if !defined(MOZILLA_PRESUME_SSE) |
|
122 bool sse_enabled = has_cpuid_bit(1u, edx, (1u<<25)); |
|
123 #endif |
|
124 |
|
125 #if !defined(MOZILLA_PRESUME_SSE2) |
|
126 bool sse2_enabled = has_cpuid_bit(1u, edx, (1u<<26)); |
|
127 #endif |
|
128 |
|
129 #if !defined(MOZILLA_PRESUME_SSE3) |
|
130 bool sse3_enabled = has_cpuid_bit(1u, ecx, (1u<<0)); |
|
131 #endif |
|
132 |
|
133 #if !defined(MOZILLA_PRESUME_SSSE3) |
|
134 bool ssse3_enabled = has_cpuid_bit(1u, ecx, (1u<<9)); |
|
135 #endif |
|
136 |
|
137 #if !defined(MOZILLA_PRESUME_SSE4A) |
|
138 bool sse4a_enabled = has_cpuid_bit(0x80000001u, ecx, (1u<<6)); |
|
139 #endif |
|
140 |
|
141 #if !defined(MOZILLA_PRESUME_SSE4_1) |
|
142 bool sse4_1_enabled = has_cpuid_bit(1u, ecx, (1u<<19)); |
|
143 #endif |
|
144 |
|
145 #if !defined(MOZILLA_PRESUME_SSE4_2) |
|
146 bool sse4_2_enabled = has_cpuid_bit(1u, ecx, (1u<<20)); |
|
147 #endif |
|
148 |
|
149 #endif |
|
150 |
|
151 } // namespace sse_private |
|
152 } // namespace mozilla |