OLD | NEW |
1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Use of this source code is governed by a BSD-style license | 3 // Use of this source code is governed by a BSD-style license |
4 // that can be found in the COPYING file in the root of the source | 4 // that can be found in the COPYING file in the root of the source |
5 // tree. An additional intellectual property rights grant can be found | 5 // tree. An additional intellectual property rights grant can be found |
6 // in the file PATENTS. All contributing project authors may | 6 // in the file PATENTS. All contributing project authors may |
7 // be found in the AUTHORS file in the root of the source tree. | 7 // be found in the AUTHORS file in the root of the source tree. |
8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
9 // | 9 // |
10 // CPU detection | 10 // CPU detection |
11 // | 11 // |
12 // Author: Christian Duvivier (cduvivier@google.com) | 12 // Author: Christian Duvivier (cduvivier@google.com) |
13 | 13 |
14 #include "./dsp.h" | 14 #include "./dsp.h" |
15 | 15 |
16 #if defined(__ANDROID__) | 16 #if defined(WEBP_ANDROID_NEON) |
17 #include <cpu-features.h> | 17 #include <cpu-features.h> |
18 #endif | 18 #endif |
19 | 19 |
20 //------------------------------------------------------------------------------ | 20 //------------------------------------------------------------------------------ |
21 // SSE2 detection. | 21 // SSE2 detection. |
22 // | 22 // |
23 | 23 |
24 // apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC. | 24 // apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC. |
25 #if (defined(__pic__) || defined(__PIC__)) && defined(__i386__) | 25 #if (defined(__pic__) || defined(__PIC__)) && defined(__i386__) |
26 static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { | 26 static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { |
27 __asm__ volatile ( | 27 __asm__ volatile ( |
28 "mov %%ebx, %%edi\n" | 28 "mov %%ebx, %%edi\n" |
29 "cpuid\n" | 29 "cpuid\n" |
30 "xchg %%edi, %%ebx\n" | 30 "xchg %%edi, %%ebx\n" |
31 : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) | 31 : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) |
32 : "a"(info_type), "c"(0)); | 32 : "a"(info_type), "c"(0)); |
33 } | 33 } |
| 34 #elif defined(__x86_64__) && \ |
| 35 (defined(__code_model_medium__) || defined(__code_model_large__)) && \ |
| 36 defined(__PIC__) |
| 37 static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { |
| 38 __asm__ volatile ( |
| 39 "xchg{q}\t{%%rbx}, %q1\n" |
| 40 "cpuid\n" |
| 41 "xchg{q}\t{%%rbx}, %q1\n" |
| 42 : "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]), |
| 43 "=d"(cpu_info[3]) |
| 44 : "a"(info_type), "c"(0)); |
| 45 } |
34 #elif defined(__i386__) || defined(__x86_64__) | 46 #elif defined(__i386__) || defined(__x86_64__) |
35 static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { | 47 static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { |
36 __asm__ volatile ( | 48 __asm__ volatile ( |
37 "cpuid\n" | 49 "cpuid\n" |
38 : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) | 50 : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) |
39 : "a"(info_type), "c"(0)); | 51 : "a"(info_type), "c"(0)); |
40 } | 52 } |
41 #elif (defined(_M_X64) || defined(_M_IX86)) && \ | 53 #elif (defined(_M_X64) || defined(_M_IX86)) && \ |
42 defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1 | 54 defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1 |
43 #include <intrin.h> | 55 #include <intrin.h> |
(...skipping 28 matching lines...) Expand all Loading... |
72 mov edx_, edx | 84 mov edx_, edx |
73 } | 85 } |
74 return ((uint64_t)edx_ << 32) | eax_; | 86 return ((uint64_t)edx_ << 32) | eax_; |
75 } | 87 } |
76 #else | 88 #else |
77 #define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains. | 89 #define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains. |
78 #endif | 90 #endif |
79 | 91 |
80 #if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2) | 92 #if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2) |
81 static int x86CPUInfo(CPUFeature feature) { | 93 static int x86CPUInfo(CPUFeature feature) { |
| 94 int max_cpuid_value; |
82 int cpu_info[4]; | 95 int cpu_info[4]; |
| 96 |
| 97 // get the highest feature value cpuid supports |
| 98 GetCPUInfo(cpu_info, 0); |
| 99 max_cpuid_value = cpu_info[0]; |
| 100 if (max_cpuid_value < 1) { |
| 101 return 0; |
| 102 } |
| 103 |
83 GetCPUInfo(cpu_info, 1); | 104 GetCPUInfo(cpu_info, 1); |
84 if (feature == kSSE2) { | 105 if (feature == kSSE2) { |
85 return 0 != (cpu_info[3] & 0x04000000); | 106 return 0 != (cpu_info[3] & 0x04000000); |
86 } | 107 } |
87 if (feature == kSSE3) { | 108 if (feature == kSSE3) { |
88 return 0 != (cpu_info[2] & 0x00000001); | 109 return 0 != (cpu_info[2] & 0x00000001); |
89 } | 110 } |
| 111 if (feature == kSSE4_1) { |
| 112 return 0 != (cpu_info[2] & 0x00080000); |
| 113 } |
90 if (feature == kAVX) { | 114 if (feature == kAVX) { |
91 // bits 27 (OSXSAVE) & 28 (256-bit AVX) | 115 // bits 27 (OSXSAVE) & 28 (256-bit AVX) |
92 if ((cpu_info[2] & 0x18000000) == 0x18000000) { | 116 if ((cpu_info[2] & 0x18000000) == 0x18000000) { |
93 // XMM state and YMM state enabled by the OS. | 117 // XMM state and YMM state enabled by the OS. |
94 return (xgetbv() & 0x6) == 0x6; | 118 return (xgetbv() & 0x6) == 0x6; |
95 } | 119 } |
96 } | 120 } |
97 if (feature == kAVX2) { | 121 if (feature == kAVX2) { |
98 if (x86CPUInfo(kAVX)) { | 122 if (x86CPUInfo(kAVX) && max_cpuid_value >= 7) { |
99 GetCPUInfo(cpu_info, 7); | 123 GetCPUInfo(cpu_info, 7); |
100 return ((cpu_info[1] & 0x00000020) == 0x00000020); | 124 return ((cpu_info[1] & 0x00000020) == 0x00000020); |
101 } | 125 } |
102 } | 126 } |
103 return 0; | 127 return 0; |
104 } | 128 } |
105 VP8CPUInfo VP8GetCPUInfo = x86CPUInfo; | 129 VP8CPUInfo VP8GetCPUInfo = x86CPUInfo; |
106 #elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test. | 130 #elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test. |
107 static int AndroidCPUInfo(CPUFeature feature) { | 131 static int AndroidCPUInfo(CPUFeature feature) { |
108 const AndroidCpuFamily cpu_family = android_getCpuFamily(); | 132 const AndroidCpuFamily cpu_family = android_getCpuFamily(); |
109 const uint64_t cpu_features = android_getCpuFeatures(); | 133 const uint64_t cpu_features = android_getCpuFeatures(); |
110 if (feature == kNEON) { | 134 if (feature == kNEON) { |
111 return (cpu_family == ANDROID_CPU_FAMILY_ARM && | 135 return (cpu_family == ANDROID_CPU_FAMILY_ARM && |
112 0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON)); | 136 0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON)); |
113 } | 137 } |
114 return 0; | 138 return 0; |
115 } | 139 } |
116 VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo; | 140 VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo; |
117 #elif defined(WEBP_USE_NEON) | 141 #elif defined(WEBP_USE_NEON) |
118 // define a dummy function to enable turning off NEON at runtime by setting | 142 // define a dummy function to enable turning off NEON at runtime by setting |
119 // VP8DecGetCPUInfo = NULL | 143 // VP8DecGetCPUInfo = NULL |
120 static int armCPUInfo(CPUFeature feature) { | 144 static int armCPUInfo(CPUFeature feature) { |
121 (void)feature; | 145 (void)feature; |
122 return 1; | 146 return 1; |
123 } | 147 } |
124 VP8CPUInfo VP8GetCPUInfo = armCPUInfo; | 148 VP8CPUInfo VP8GetCPUInfo = armCPUInfo; |
125 #elif defined(WEBP_USE_MIPS32) | 149 #elif defined(WEBP_USE_MIPS32) || defined(WEBP_USE_MIPS_DSP_R2) |
126 static int mipsCPUInfo(CPUFeature feature) { | 150 static int mipsCPUInfo(CPUFeature feature) { |
127 (void)feature; | 151 if ((feature == kMIPS32) || (feature == kMIPSdspR2)) { |
128 return 1; | 152 return 1; |
| 153 } else { |
| 154 return 0; |
| 155 } |
| 156 |
129 } | 157 } |
130 VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo; | 158 VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo; |
131 #else | 159 #else |
132 VP8CPUInfo VP8GetCPUInfo = NULL; | 160 VP8CPUInfo VP8GetCPUInfo = NULL; |
133 #endif | 161 #endif |
134 | 162 |
OLD | NEW |