]> git.sesse.net Git - x264/blob - common/cpu.c
499a076148f080317e115eb597c74fdb7839677e
[x264] / common / cpu.c
1 /*****************************************************************************
2  * cpu.c: h264 encoder library
3  *****************************************************************************
4  * Copyright (C) 2003 Laurent Aimar
5  * $Id: cpu.c,v 1.1 2004/06/03 19:27:06 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_STDINT_H
25 #include <stdint.h>
26 #else
27 #include <inttypes.h>
28 #endif
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32
33 #include "x264.h"
34 #include "cpu.h"
35
36 #ifdef ARCH_X86
37 extern int  x264_cpu_cpuid_test( void );
38 extern uint32_t  x264_cpu_cpuid( uint32_t op, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx );
39 extern void x264_emms( void );
40
41 uint32_t x264_cpu_detect( void )
42 {
43     uint32_t cpu = 0;
44
45     uint32_t eax, ebx, ecx, edx;
46     int      b_amd;
47
48
49     if( !x264_cpu_cpuid_test() )
50     {
51         /* No cpuid */
52         return 0;
53     }
54
55     x264_cpu_cpuid( 0, &eax, &ebx, &ecx, &edx);
56     if( eax == 0 )
57     {
58         return 0;
59     }
60     b_amd   = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
61
62     x264_cpu_cpuid( 1, &eax, &ebx, &ecx, &edx );
63     if( (edx&0x00800000) == 0 )
64     {
65         /* No MMX */
66         return 0;
67     }
68     cpu = X264_CPU_MMX;
69     if( (edx&0x02000000) )
70     {
71         /* SSE - identical to AMD MMX extensions */
72         cpu |= X264_CPU_MMXEXT|X264_CPU_SSE;
73     }
74     if( (edx&0x04000000) )
75     {
76         /* Is it OK ? */
77         cpu |= X264_CPU_SSE2;
78     }
79
80     x264_cpu_cpuid( 0x80000000, &eax, &ebx, &ecx, &edx );
81     if( eax < 0x80000001 )
82     {
83         /* no extended capabilities */
84         return cpu;
85     }
86
87     x264_cpu_cpuid( 0x80000001, &eax, &ebx, &ecx, &edx );
88     if( edx&0x80000000 )
89     {
90         cpu |= X264_CPU_3DNOW;
91     }
92     if( b_amd && (edx&0x00400000) )
93     {
94         /* AMD MMX extensions */
95         cpu |= X264_CPU_MMXEXT;
96     }
97
98     return cpu;
99 }
100
101 void     x264_cpu_restore( uint32_t cpu )
102 {
103     if( cpu&(X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_3DNOW|X264_CPU_3DNOWEXT) )
104     {
105         x264_emms();
106     }
107 }
108
109
110 #if 0
111 /*
112  * XXX: adapted from libmpeg2 */
113 #if 0
114 #define cpuid(op,eax,ebx,ecx,edx)   \
115     __asm__ ("push %%ebx\n\t"       \
116              "cpuid\n\t"            \
117              "movl %%ebx,%1\n\t"    \
118              "pop %%ebx"        \
119              : "=a" (eax),      \
120                "=r" (ebx),      \
121                "=c" (ecx),      \
122                "=d" (edx)       \
123              : "a" (op)         \
124              : "cc")
125 #endif
126
127 uint32_t x264_cpu_detect( void )
128 {
129     uint32_t cpu = 0;
130
131     uint32_t eax, ebx, ecx, edx;
132     int      b_amd;
133
134
135     /* Test if cpuid is supported */
136     asm volatile(
137         "pushf\n"
138         "pushf\n"
139         "pop %0\n"
140         "movl %0,%1\n"
141         "xorl $0x200000,%0\n"
142         "push %0\n"
143         "popf\n"
144         "pushf\n"
145         "pop %0\n"
146         "popf\n"
147          : "=r" (eax), "=r" (ebx) : : "cc");
148
149     if( eax == ebx )
150     {
151         /* No cpuid */
152         return 0;
153     }
154
155     cpuid( 0, eax, ebx, ecx, edx);
156     if( eax == 0 )
157     {
158         return 0;
159     }
160     b_amd   = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
161
162     cpuid( 1, eax, ebx, ecx, edx );
163     if( (edx&0x00800000) == 0 )
164     {
165         /* No MMX */
166         return 0;
167     }
168     cpu = X264_CPU_MMX;
169     if( (edx&0x02000000) )
170     {
171         /* SSE - identical to AMD MMX extensions */
172         cpu |= X264_CPU_MMXEXT|X264_CPU_SSE;
173     }
174     if( (edx&0x04000000) )
175     {
176         /* Is it OK ? */
177         cpu |= X264_CPU_SSE2;
178     }
179
180     cpuid( 0x80000000, eax, ebx, ecx, edx );
181     if( eax < 0x80000001 )
182     {
183         /* no extended capabilities */
184         return cpu;
185     }
186
187     cpuid( 0x80000001, eax, ebx, ecx, edx );
188     if( edx&0x80000000 )
189     {
190         cpu |= X264_CPU_3DNOW;
191     }
192     if( b_amd && (edx&0x00400000) )
193     {
194         /* AMD MMX extensions */
195         cpu |= X264_CPU_MMXEXT;
196     }
197
198     return cpu;
199 }
200 #endif
201
202 #elif defined( ARCH_PPC )
203
204 #ifdef SYS_MACOSX
205 #include <sys/sysctl.h>
206 uint32_t x264_cpu_detect( void )
207 {
208     /* Thank you VLC */
209     uint32_t cpu = 0;
210     int      selectors[2] = { CTL_HW, HW_VECTORUNIT };
211     int      has_altivec = 0;
212     size_t   length = sizeof( has_altivec );
213     int      error = sysctl( selectors, 2, &has_altivec, &length, NULL, 0 );
214
215     if( error == 0 && has_altivec != 0 )
216     {
217         cpu |= X264_CPU_ALTIVEC;
218     }
219
220     return cpu;
221 }
222
223 #elif defined( SYS_LINUX )
224 uint32_t x264_cpu_detect( void )
225 {
226     /* FIXME (Linux PPC) */
227     return X264_CPU_ALTIVEC;
228 }
229 #endif
230
231 void     x264_cpu_restore( uint32_t cpu )
232 {
233 }
234
235 #else
236
237 uint32_t x264_cpu_detect( void )
238 {
239     return 0;
240 }
241
242 void     x264_cpu_restore( uint32_t cpu )
243 {
244 }
245
246 #endif
247